From 471469d30facd25ed3072524694e369aeb72082c Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Tue, 12 Sep 2023 18:13:53 +0200
Subject: [PATCH] Merge commit '98363cbf6a7c3f8b571a7d92a3c645bb4376e4a6' into
 clippyup

---
 .github/driver.sh                             |   2 +-
 .github/workflows/clippy_bors.yml             |  33 +-
 CHANGELOG.md                                  |   5 +
 Cargo.toml                                    |   2 +-
 book/src/SUMMARY.md                           |   3 +
 book/src/development/emitting_lints.md        | 217 ++++++++
 book/src/development/trait_checking.md        | 105 ++++
 book/src/development/writing_tests.md         | 218 ++++++++
 book/src/lint_configuration.md                |  24 +
 clippy_lints/src/declared_lints.rs            |   6 +-
 .../src/default_union_representation.rs       |   3 +
 clippy_lints/src/dereference.rs               |  31 +-
 clippy_lints/src/derivable_impls.rs           |   3 +-
 clippy_lints/src/disallowed_macros.rs         |  11 +-
 clippy_lints/src/doc.rs                       |   2 +-
 clippy_lints/src/if_then_some_else_none.rs    |  18 +-
 clippy_lints/src/ignored_unit_patterns.rs     |  13 +-
 clippy_lints/src/implied_bounds_in_impls.rs   | 242 ++++++---
 clippy_lints/src/lib.rs                       |   9 +-
 clippy_lints/src/loops/explicit_iter_loop.rs  |  17 +-
 clippy_lints/src/loops/mod.rs                 |  10 +-
 clippy_lints/src/loops/never_loop.rs          | 268 +++++-----
 clippy_lints/src/manual_range_patterns.rs     | 129 +++--
 .../src/methods/iter_out_of_bounds.rs         | 106 ++++
 .../src/methods/iter_overeager_cloned.rs      |   2 +-
 clippy_lints/src/methods/mod.rs               |  58 ++-
 .../src/missing_asserts_for_indexing.rs       | 391 +++++++++++++++
 ...orrect_impls.rs => non_canonical_impls.rs} |  45 +-
 .../src/operators/arithmetic_side_effects.rs  |  16 +-
 clippy_lints/src/operators/float_cmp.rs       |   2 +-
 clippy_lints/src/raw_strings.rs               |  89 +++-
 clippy_lints/src/renamed_lints.rs             |   4 +-
 .../src/slow_vector_initialization.rs         |  12 +-
 clippy_lints/src/std_instead_of_core.rs       |  26 +-
 .../src/undocumented_unsafe_blocks.rs         | 107 ++--
 clippy_lints/src/unit_return_expecting_ord.rs |   2 +-
 clippy_lints/src/unwrap.rs                    | 111 ++++-
 clippy_lints/src/utils/conf.rs                |  20 +
 clippy_utils/src/lib.rs                       |   4 +-
 clippy_utils/src/paths.rs                     |   2 +
 clippy_utils/src/source.rs                    |   2 +-
 clippy_utils/src/sugg.rs                      |   2 +-
 clippy_utils/src/ty.rs                        |   7 +-
 clippy_utils/src/ty/type_certainty/mod.rs     |   2 +-
 clippy_utils/src/usage.rs                     |  13 +-
 rust-toolchain                                |   2 +-
 tests/compile-test.rs                         |  45 +-
 .../cargo_common_metadata/fail/Cargo.stderr   |   1 +
 .../fail_publish/Cargo.stderr                 |   1 +
 .../fail_publish_true/Cargo.stderr            |   1 +
 .../ui-cargo/duplicate_mod/fail/Cargo.stderr  |   1 +
 tests/ui-cargo/feature_name/fail/Cargo.stderr |   2 +
 .../module_style/fail_mod/Cargo.stderr        |   1 +
 .../module_style/fail_mod_remap/Cargo.stderr  |   1 +
 .../module_style/fail_no_mod/Cargo.stderr     |   1 +
 .../multiple_crate_versions/fail/Cargo.stderr |   1 +
 .../wildcard_dependencies/fail/Cargo.stderr   |   1 +
 tests/ui-internal/check_formulation.stderr    |   1 +
 tests/ui-internal/if_chain_style.stderr       |   1 +
 tests/ui-internal/invalid_paths.stderr        |   1 +
 ...unnecessary_def_path_hardcoded_path.stderr |   1 +
 .../disallowed_macros/auxiliary/macros.rs     |  15 +
 tests/ui-toml/disallowed_macros/clippy.toml   |   2 +
 .../disallowed_macros/disallowed_macros.rs    |   5 +-
 .../disallowed_macros.stderr                  |  22 +-
 .../auxiliary/proc_macros.rs                  | 469 ------------------
 .../excessive_nesting/excessive_nesting.rs    |   4 +-
 .../toml_unknown_key/conf_unknown_key.stderr  |   2 +
 .../auxiliary/proc_macro_unsafe.rs            |  13 -
 .../undocumented_unsafe_blocks.rs             |  16 +-
 tests/ui/bool_comparison.fixed                |   2 +-
 tests/ui/bool_comparison.rs                   |   2 +-
 ...ze_32bit.stderr => cast_size.32bit.stderr} |  56 ++-
 ...ast_size.stderr => cast_size.64bit.stderr} |  34 +-
 tests/ui/cast_size.rs                         |  31 +-
 tests/ui/cast_size_32bit.rs                   |  56 ---
 .../ui/checked_unwrap/simple_conditionals.rs  |  51 ++
 .../checked_unwrap/simple_conditionals.stderr |  70 ++-
 tests/ui/clone_on_copy_impl.rs                |   2 +-
 tests/ui/crashes/ice-11337.rs                 |   9 +
 tests/ui/crashes/ice-11422.fixed              |  25 +
 tests/ui/crashes/ice-11422.rs                 |  25 +
 tests/ui/crashes/ice-11422.stderr             |  16 +
 tests/ui/crashes/ice-360.rs                   |   3 +-
 tests/ui/crashes/ice-360.stderr               |  20 +-
 tests/ui/derivable_impls.fixed                |  13 +
 tests/ui/derivable_impls.rs                   |  13 +
 tests/ui/derive.rs                            |   6 +-
 tests/ui/derive.stderr                        |  20 +-
 tests/ui/derive_ord_xor_partial_ord.rs        |   2 +-
 tests/ui/empty_loop.rs                        |   3 +
 tests/ui/empty_loop.stderr                    |   4 +-
 tests/ui/enum_clike_unportable_variant.rs     |   2 +-
 tests/ui/enum_clike_unportable_variant.stderr |  17 +-
 tests/ui/explicit_auto_deref.fixed            |  30 +-
 tests/ui/explicit_auto_deref.rs               |  28 ++
 tests/ui/explicit_auto_deref.stderr           |  12 +-
 tests/ui/explicit_iter_loop.fixed             |   7 +-
 tests/ui/explicit_iter_loop.rs                |   1 +
 tests/ui/explicit_iter_loop.stderr            |  65 +--
 tests/ui/float_cmp.rs                         |  13 +
 tests/ui/float_cmp.stderr                     |  12 +-
 ...stderr => fn_to_numeric_cast.32bit.stderr} |  62 +--
 ...stderr => fn_to_numeric_cast.64bit.stderr} |  44 +-
 tests/ui/fn_to_numeric_cast.rs                |  27 +-
 tests/ui/fn_to_numeric_cast_32bit.rs          |  80 ---
 tests/ui/if_then_some_else_none.rs            |  12 +
 tests/ui/ignored_unit_patterns.fixed          |  16 +-
 tests/ui/ignored_unit_patterns.rs             |  16 +-
 tests/ui/ignored_unit_patterns.stderr         |  10 +-
 tests/ui/implied_bounds_in_impls.fixed        |  57 +++
 tests/ui/implied_bounds_in_impls.rs           |  57 +++
 tests/ui/implied_bounds_in_impls.stderr       |  74 ++-
 tests/ui/iter_out_of_bounds.rs                |  71 +++
 tests/ui/iter_out_of_bounds.stderr            | 119 +++++
 tests/ui/iter_overeager_cloned.fixed          |   6 +-
 tests/ui/iter_overeager_cloned.rs             |   2 -
 tests/ui/iter_overeager_cloned.stderr         |  18 +-
 tests/ui/iter_skip_next.fixed                 |   1 +
 tests/ui/iter_skip_next.rs                    |   1 +
 tests/ui/iter_skip_next.stderr                |  14 +-
 tests/ui/iter_skip_next_unfixable.rs          |   2 +-
 tests/ui/iter_skip_zero.fixed                 |   2 +-
 tests/ui/iter_skip_zero.rs                    |   2 +-
 tests/ui/large_enum_variant.32bit.stderr      | 280 +++++++++++
 ...stderr => large_enum_variant.64bit.stderr} |  44 +-
 tests/ui/large_enum_variant.rs                |   1 +
 tests/ui/manual_range_patterns.fixed          |  17 +-
 tests/ui/manual_range_patterns.rs             |  11 +
 tests/ui/manual_range_patterns.stderr         |  66 ++-
 tests/ui/missing_asserts_for_indexing.fixed   | 121 +++++
 tests/ui/missing_asserts_for_indexing.rs      | 121 +++++
 tests/ui/missing_asserts_for_indexing.stderr  | 253 ++++++++++
 .../missing_asserts_for_indexing_unfixable.rs |  49 ++
 ...sing_asserts_for_indexing_unfixable.stderr | 164 ++++++
 tests/ui/needless_borrow.fixed                |  13 +
 tests/ui/needless_borrow.rs                   |  13 +
 tests/ui/needless_raw_string.fixed            |  13 +-
 tests/ui/needless_raw_string.rs               |  13 +-
 tests/ui/needless_raw_string.stderr           |  48 +-
 tests/ui/needless_raw_string_hashes.fixed     |  19 +-
 tests/ui/needless_raw_string_hashes.rs        |  19 +-
 tests/ui/needless_raw_string_hashes.stderr    | 144 +++++-
 tests/ui/never_loop.rs                        |  55 +-
 tests/ui/never_loop.stderr                    |  27 +-
 ...e.fixed => non_canonical_clone_impl.fixed} |   0
 ...py_type.rs => non_canonical_clone_impl.rs} |   0
 ...stderr => non_canonical_clone_impl.stderr} |  19 +-
 ...d => non_canonical_partial_ord_impl.fixed} |   0
 ...e.rs => non_canonical_partial_ord_impl.rs} |   0
 ... => non_canonical_partial_ord_impl.stderr} |  11 +-
 ..._canonical_partial_ord_impl_fully_qual.rs} |   3 -
 ...onical_partial_ord_impl_fully_qual.stderr} |  14 +-
 tests/ui/rename.fixed                         |   8 +-
 tests/ui/rename.rs                            |   8 +-
 tests/ui/rename.stderr                        | 132 ++---
 tests/ui/result_large_err.rs                  |   2 +
 tests/ui/result_large_err.stderr              |  24 +-
 tests/ui/similar_names.rs                     |   1 +
 tests/ui/similar_names.stderr                 |  28 +-
 tests/ui/single_call_fn.rs                    |   1 +
 tests/ui/single_call_fn.stderr                |  16 +-
 tests/ui/slow_vector_initialization.rs        |  16 +-
 tests/ui/slow_vector_initialization.stderr    |  12 +-
 tests/ui/std_instead_of_core.fixed            |  62 +++
 tests/ui/std_instead_of_core.rs               |   1 -
 tests/ui/std_instead_of_core.stderr           |  71 +--
 tests/ui/transmute_32bit.stderr               |  30 +-
 .../unnecessary_struct_initialization.fixed   |   2 +-
 tests/ui/unnecessary_struct_initialization.rs |   2 +-
 tests/ui/vec.fixed                            |   1 +
 tests/ui/vec.rs                               |   1 +
 tests/ui/vec.stderr                           |  10 +-
 tests/ui/write_literal_2.stderr               |   4 +-
 174 files changed, 4682 insertions(+), 1635 deletions(-)
 create mode 100644 book/src/development/emitting_lints.md
 create mode 100644 book/src/development/trait_checking.md
 create mode 100644 book/src/development/writing_tests.md
 create mode 100644 clippy_lints/src/methods/iter_out_of_bounds.rs
 create mode 100644 clippy_lints/src/missing_asserts_for_indexing.rs
 rename clippy_lints/src/{incorrect_impls.rs => non_canonical_impls.rs} (88%)
 delete mode 100644 tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs
 delete mode 100644 tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs
 rename tests/ui/{cast_size_32bit.stderr => cast_size.32bit.stderr} (78%)
 rename tests/ui/{cast_size.stderr => cast_size.64bit.stderr} (94%)
 delete mode 100644 tests/ui/cast_size_32bit.rs
 create mode 100644 tests/ui/crashes/ice-11337.rs
 create mode 100644 tests/ui/crashes/ice-11422.fixed
 create mode 100644 tests/ui/crashes/ice-11422.rs
 create mode 100644 tests/ui/crashes/ice-11422.stderr
 rename tests/ui/{fn_to_numeric_cast_32bit.stderr => fn_to_numeric_cast.32bit.stderr} (70%)
 rename tests/ui/{fn_to_numeric_cast.stderr => fn_to_numeric_cast.64bit.stderr} (85%)
 delete mode 100644 tests/ui/fn_to_numeric_cast_32bit.rs
 create mode 100644 tests/ui/iter_out_of_bounds.rs
 create mode 100644 tests/ui/iter_out_of_bounds.stderr
 create mode 100644 tests/ui/large_enum_variant.32bit.stderr
 rename tests/ui/{large_enum_variant.stderr => large_enum_variant.64bit.stderr} (91%)
 create mode 100644 tests/ui/missing_asserts_for_indexing.fixed
 create mode 100644 tests/ui/missing_asserts_for_indexing.rs
 create mode 100644 tests/ui/missing_asserts_for_indexing.stderr
 create mode 100644 tests/ui/missing_asserts_for_indexing_unfixable.rs
 create mode 100644 tests/ui/missing_asserts_for_indexing_unfixable.stderr
 rename tests/ui/{incorrect_clone_impl_on_copy_type.fixed => non_canonical_clone_impl.fixed} (100%)
 rename tests/ui/{incorrect_clone_impl_on_copy_type.rs => non_canonical_clone_impl.rs} (100%)
 rename tests/ui/{incorrect_clone_impl_on_copy_type.stderr => non_canonical_clone_impl.stderr} (54%)
 rename tests/ui/{incorrect_partial_ord_impl_on_ord_type.fixed => non_canonical_partial_ord_impl.fixed} (100%)
 rename tests/ui/{incorrect_partial_ord_impl_on_ord_type.rs => non_canonical_partial_ord_impl.rs} (100%)
 rename tests/ui/{incorrect_partial_ord_impl_on_ord_type.stderr => non_canonical_partial_ord_impl.stderr} (63%)
 rename tests/ui/{incorrect_partial_ord_impl_on_ord_type_fully_qual.rs => non_canonical_partial_ord_impl_fully_qual.rs} (82%)
 rename tests/ui/{incorrect_partial_ord_impl_on_ord_type_fully_qual.stderr => non_canonical_partial_ord_impl_fully_qual.stderr} (67%)
 create mode 100644 tests/ui/std_instead_of_core.fixed

diff --git a/.github/driver.sh b/.github/driver.sh
index 798782340ee..c05c6ecc115 100644
--- a/.github/driver.sh
+++ b/.github/driver.sh
@@ -30,7 +30,7 @@ unset CARGO_MANIFEST_DIR
 # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1
 # FIXME: How to match the clippy invocation in compile-test.rs?
 ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1
-sed -e "s,tests/ui,\$DIR," -e "/= help/d" double_neg.stderr >normalized.stderr
+sed -e "s,tests/ui,\$DIR," -e "/= help: for/d" double_neg.stderr > normalized.stderr
 diff -u normalized.stderr tests/ui/double_neg.stderr
 
 # make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml
index 5c69714bc1e..9b96f8dc253 100644
--- a/.github/workflows/clippy_bors.yml
+++ b/.github/workflows/clippy_bors.yml
@@ -52,24 +52,14 @@ jobs:
     needs: changelog
     strategy:
       matrix:
-        os: [ubuntu-latest, windows-latest, macos-latest]
-        host: [x86_64-unknown-linux-gnu, i686-unknown-linux-gnu, x86_64-apple-darwin, x86_64-pc-windows-msvc]
-        exclude:
+        include:
         - os: ubuntu-latest
-          host: x86_64-apple-darwin
+          host: x86_64-unknown-linux-gnu
         - os: ubuntu-latest
-          host: x86_64-pc-windows-msvc
-        - os: macos-latest
-          host: x86_64-unknown-linux-gnu
-        - os: macos-latest
-          host: i686-unknown-linux-gnu
-        - os: macos-latest
-          host: x86_64-pc-windows-msvc
-        - os: windows-latest
-          host: x86_64-unknown-linux-gnu
-        - os: windows-latest
           host: i686-unknown-linux-gnu
         - os: windows-latest
+          host: x86_64-pc-windows-msvc
+        - os: macos-latest
           host: x86_64-apple-darwin
 
     runs-on: ${{ matrix.os }}
@@ -84,8 +74,17 @@ jobs:
     - name: Checkout
       uses: actions/checkout@v3
 
+    - name: Install i686 dependencies
+      if: matrix.host == 'i686-unknown-linux-gnu'
+      run: |
+        sudo dpkg --add-architecture i386
+        sudo apt-get update
+        sudo apt-get install gcc-multilib zlib1g-dev:i386
+
     - name: Install toolchain
-      run: rustup show active-toolchain
+      run: |
+        rustup set default-host ${{ matrix.host }}
+        rustup show active-toolchain
 
     # Run
     - name: Set LD_LIBRARY_PATH (Linux)
@@ -109,11 +108,11 @@ jobs:
       run: cargo build --tests --features deny-warnings,internal
 
     - name: Test
-      if: runner.os == 'Linux'
+      if: matrix.host == 'x86_64-unknown-linux-gnu'
       run: cargo test --features deny-warnings,internal
 
     - name: Test
-      if: runner.os != 'Linux'
+      if: matrix.host != 'x86_64-unknown-linux-gnu'
       run: cargo test --features deny-warnings,internal -- --skip dogfood
 
     - name: Test clippy_lints
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92cc19edb05..a7ae4a0ee2c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5031,6 +5031,7 @@ Released 2018-09-13
 [`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth_zero
 [`iter_on_empty_collections`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_empty_collections
 [`iter_on_single_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_single_items
+[`iter_out_of_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_out_of_bounds
 [`iter_overeager_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_overeager_cloned
 [`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next
 [`iter_skip_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_zero
@@ -5131,6 +5132,7 @@ Released 2018-09-13
 [`misnamed_getters`]: https://rust-lang.github.io/rust-clippy/master/index.html#misnamed_getters
 [`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op
 [`missing_assert_message`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_assert_message
+[`missing_asserts_for_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_asserts_for_indexing
 [`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn
 [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
 [`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames
@@ -5204,6 +5206,8 @@ Released 2018-09-13
 [`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
 [`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
 [`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
+[`non_canonical_clone_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_canonical_clone_impl
+[`non_canonical_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_canonical_partial_ord_impl
 [`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
 [`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
@@ -5570,4 +5574,5 @@ Released 2018-09-13
 [`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
 [`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments
 [`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates
+[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow
 <!-- end autogenerated links to configuration documentation -->
diff --git a/Cargo.toml b/Cargo.toml
index 7c78beb5dde..2d8b590dbe3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,7 +27,7 @@ tempfile = { version = "3.2", optional = true }
 termize = "0.1"
 
 [dev-dependencies]
-ui_test = "0.18.1"
+ui_test = "0.20"
 tester = "0.9"
 regex = "1.5"
 toml = "0.7.3"
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index daaefd06a97..b02457307d7 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -14,8 +14,11 @@
     - [Basics](development/basics.md)
     - [Adding Lints](development/adding_lints.md)
     - [Defining Lints](development/defining_lints.md)
+    - [Writing tests](development/writing_tests.md)
     - [Lint Passes](development/lint_passes.md)
+    - [Emitting lints](development/emitting_lints.md)
     - [Type Checking](development/type_checking.md)
+    - [Trait Checking](development/trait_checking.md)
     - [Method Checking](development/method_checking.md)
     - [Macro Expansions](development/macro_expansions.md)
     - [Common Tools](development/common_tools_writing_lints.md)
diff --git a/book/src/development/emitting_lints.md b/book/src/development/emitting_lints.md
new file mode 100644
index 00000000000..a12f6aa91b3
--- /dev/null
+++ b/book/src/development/emitting_lints.md
@@ -0,0 +1,217 @@
+# Emitting a lint
+
+Once we have [defined a lint](defining_lints.md), written [UI
+tests](writing_tests.md) and chosen [the lint pass](lint_passes.md) for the lint,
+we can begin the implementation of the lint logic so that we can emit it and
+gradually work towards a lint that behaves as expected.
+
+Note that we will not go into concrete implementation of a lint logic in this
+chapter. We will go into details in later chapters as well as in two examples of
+real Clippy lints.
+
+To emit a lint, we must implement a pass (see [Lint Passes](lint_passes.md)) for
+the lint that we have declared. In this example we'll implement a "late" lint,
+so take a look at the [LateLintPass][late_lint_pass] documentation, which
+provides an abundance of methods that we can implement for our lint.
+
+```rust
+pub trait LateLintPass<'tcx>: LintPass {
+    // Trait methods
+}
+```
+
+By far the most common method used for Clippy lints is [`check_expr`
+method][late_check_expr], this is because Rust is an expression language and,
+more often than not, the lint we want to work on must examine expressions.
+
+> _Note:_ If you don't fully understand what expressions are in Rust, take a
+> look at the official documentation on [expressions][rust_expressions]
+
+Other common ones include the [`check_fn` method][late_check_fn] and the
+[`check_item` method][late_check_item].
+
+### Emitting a lint
+
+Inside the trait method that we implement, we can write down the lint logic and
+emit the lint with suggestions.
+
+Clippy's [diagnostics] provides quite a few diagnostic functions that we can use
+to emit lints. Take a look at the documentation to pick one that suits your
+lint's needs the best. Some common ones you will encounter in the Clippy
+repository includes:
+
+- [`span_lint`]: Emits a lint without providing any other information
+- [`span_lint_and_note`]: Emits a lint and adds a note
+- [`span_lint_and_help`]: Emits a lint and provides a helpful message
+- [`span_lint_and_sugg`]: Emits a lint and provides a suggestion to fix the code
+- [`span_lint_and_then`]: Like `span_lint`, but allows for a lot of output
+  customization.
+
+```rust
+impl<'tcx> LateLintPass<'tcx> for LintName {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)  {
+        // Imagine that `some_lint_expr_logic` checks for requirements for emitting the lint
+        if some_lint_expr_logic(expr) {
+            span_lint_and_help(
+                cx, // < The context
+                LINT_NAME, // < The name of the lint in ALL CAPS
+                expr.span, // < The span to lint
+                "message on why the lint is emitted",
+                None, // < An optional help span (to highlight something in the lint)
+                "message that provides a helpful suggestion",
+            );
+        }
+    }
+}
+```
+
+> Note: The message should be matter of fact and avoid capitalization and
+> punctuation. If multiple sentences are needed, the messages should probably be
+> split up into an error + a help / note / suggestion message.
+
+## Suggestions: Automatic fixes
+
+Some lints know what to change in order to fix the code. For example, the lint
+[`range_plus_one`][range_plus_one] warns for ranges where the user wrote `x..y +
+1` instead of using an [inclusive range][inclusive_range] (`x..=y`). The fix to
+this code would be changing the `x..y + 1` expression to `x..=y`. **This is
+where suggestions come in**.
+
+A suggestion is a change that the lint provides to fix the issue it is linting.
+The output looks something like this (from the example earlier):
+
+```text
+error: an inclusive range would be more readable
+  --> $DIR/range_plus_minus_one.rs:37:14
+   |
+LL |     for _ in 1..1 + 1 {}
+   |              ^^^^^^^^ help: use: `1..=1`
+```
+
+**Not all suggestions are always right**, some of them require human
+supervision, that's why we have [Applicability][applicability].
+
+Applicability indicates confidence in the correctness of the suggestion, some
+are always right (`Applicability::MachineApplicable`), but we use
+`Applicability::MaybeIncorrect` and others when talking about a suggestion that
+may be incorrect.
+
+### Example
+
+The same lint `LINT_NAME` but that emits a suggestion would look something like this:
+
+```rust
+impl<'tcx> LateLintPass<'tcx> for LintName {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)  {
+        // Imagine that `some_lint_expr_logic` checks for requirements for emitting the lint
+        if some_lint_expr_logic(expr) {
+            span_lint_and_sugg( // < Note this change
+                cx,
+                LINT_NAME,
+                span,
+                "message on why the lint is emitted",
+                "use",
+                format!("foo + {} * bar", snippet(cx, expr.span, "<default>")), // < Suggestion
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+}
+```
+
+Suggestions generally use the [`format!`][format_macro] macro to interpolate the
+old values with the new ones. To get code snippets, use one of the `snippet*`
+functions from `clippy_utils::source`.
+
+## How to choose between notes, help messages and suggestions
+
+Notes are presented separately from the main lint message, they provide useful
+information that the user needs to understand why the lint was activated. They
+are the most helpful when attached to a span.
+
+Examples:
+
+### Notes
+
+```text
+error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
+  --> $DIR/drop_forget_ref.rs:10:5
+   |
+10 |     forget(&SomeStruct);
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::forget-ref` implied by `-D warnings`
+note: argument has type &SomeStruct
+  --> $DIR/drop_forget_ref.rs:10:12
+   |
+10 |     forget(&SomeStruct);
+   |            ^^^^^^^^^^^
+```
+
+### Help Messages
+
+Help messages are specifically to help the user. These are used in situation
+where you can't provide a specific machine applicable suggestion. They can also
+be attached to a span.
+
+Example:
+
+```text
+error: constant division of 0.0 with 0.0 will always result in NaN
+  --> $DIR/zero_div_zero.rs:6:25
+   |
+6  |     let other_f64_nan = 0.0f64 / 0.0;
+   |                         ^^^^^^^^^^^^
+   |
+   = help: consider using `f64::NAN` if you would like a constant representing NaN
+```
+
+### Suggestions
+
+Suggestions are the most helpful, they are changes to the source code to fix the
+error. The magic in suggestions is that tools like `rustfix` can detect them and
+automatically fix your code.
+
+Example:
+
+```text
+error: This `.fold` can be more succinctly expressed as `.any`
+--> $DIR/methods.rs:390:13
+    |
+390 |     let _ = (0..3).fold(false, |acc, x| acc || x > 2);
+    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)`
+    |
+```
+
+### Snippets
+
+Snippets are pieces of the source code (as a string), they are extracted
+generally using the [`snippet`][snippet_fn] function.
+
+For example, if you want to know how an item looks (and you know the item's
+span), you could use `snippet(cx, span, "..")`.
+
+## Final: Run UI Tests to Emit the Lint
+
+Now, if we run our [UI test](writing_tests.md), we should see that Clippy now
+produces output that contains the lint message we designed.
+
+The next step is to implement the logic properly, which is a detail that we will
+cover in the next chapters.
+
+[diagnostics]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/index.html
+[late_check_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html#method.check_expr
+[late_check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html#method.check_fn
+[late_check_item]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html#method.check_item
+[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
+[rust_expressions]: https://doc.rust-lang.org/reference/expressions.html
+[`span_lint`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint.html
+[`span_lint_and_note`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_note.html
+[`span_lint_and_help`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_help.html
+[`span_lint_and_sugg`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_sugg.html
+[`span_lint_and_then`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_then.html
+[range_plus_one]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
+[inclusive_range]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html
+[applicability]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_errors/enum.Applicability.html
+[snippet_fn]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/source/fn.snippet.html
+[format_macro]: https://doc.rust-lang.org/std/macro.format.html
diff --git a/book/src/development/trait_checking.md b/book/src/development/trait_checking.md
new file mode 100644
index 00000000000..fb263922cf8
--- /dev/null
+++ b/book/src/development/trait_checking.md
@@ -0,0 +1,105 @@
+# Trait Checking
+
+Besides [type checking](type_checking.md), we might want to examine if
+a specific type `Ty` implements certain trait when implementing a lint.
+There are three approaches to achieve this, depending on if the target trait
+that we want to examine has a [diagnostic item][diagnostic_items],
+[lang item][lang_items], or neither.
+
+## Using Diagnostic Items
+
+As explained in the [Rust Compiler Development Guide][rustc_dev_guide], diagnostic items
+are introduced for identifying types via [Symbols][symbol].
+
+For instance, if we want to examine whether an expression implements
+the `Iterator` trait, we could simply write the following code,
+providing the `LateContext` (`cx`), our expression at hand, and
+the symbol of the trait in question:
+
+```rust
+use clippy_utils::is_trait_method;
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_span::symbol::sym;
+
+impl LateLintPass<'_> for CheckIteratorTraitLint {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+		let implements_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
+    		implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[])
+		});
+		if implements_iterator {
+			// [...]
+		}
+
+    }
+}
+```
+
+> **Note**: Refer to [this index][symbol_index] for all the defined `Symbol`s.
+
+## Using Lang Items
+
+Besides diagnostic items, we can also use [`lang_items`][lang_items].
+Take a look at the documentation to find that `LanguageItems` contains
+all language items defined in the compiler.
+
+Using one of its `*_trait` method, we could obtain the [DefId] of any
+specific item, such as `Clone`, `Copy`, `Drop`, `Eq`, which are familiar
+to many Rustaceans.
+
+For instance, if we want to examine whether an expression `expr` implements
+`Drop` trait, we could access `LanguageItems` via our `LateContext`'s
+[TyCtxt], which provides a `lang_items` method that will return the id of
+`Drop` trait to us. Then, by calling Clippy utils function `implements_trait`
+we can check that the `Ty` of the `expr` implements the trait:
+
+```rust
+use clippy_utils::implements_trait;
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+
+impl LateLintPass<'_> for CheckDropTraitLint {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        let ty = cx.typeck_results().expr_ty(expr);
+        if cx.tcx.lang_items()
+            .drop_trait()
+            .map_or(false, |id| implements_trait(cx, ty, id, &[])) {
+                println!("`expr` implements `Drop` trait!");
+            }
+    }
+}
+```
+
+## Using Type Path
+
+If neither diagnostic item nor a language item is available, we can use
+[`clippy_utils::paths`][paths] with the `match_trait_method` to determine trait
+implementation.
+
+> **Note**: This approach should be avoided if possible, the best thing to do would be to make a PR to [`rust-lang/rust`][rust] adding a diagnostic item.
+
+Below, we check if the given `expr` implements the `Iterator`'s trait method `cloned` :
+
+```rust
+use clippy_utils::{match_trait_method, paths};
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+
+impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if match_trait_method(cx, expr, &paths::CORE_ITER_CLONED) {
+            println!("`expr` implements `CORE_ITER_CLONED` trait!");
+        }
+    }
+}
+```
+
+[DefId]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
+[diagnostic_items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html
+[lang_items]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/struct.LanguageItems.html
+[paths]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/paths.rs
+[rustc_dev_guide]: https://rustc-dev-guide.rust-lang.org/
+[symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html
+[symbol_index]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/sym/index.html
+[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
+[rust]: https://github.com/rust-lang/rust
diff --git a/book/src/development/writing_tests.md b/book/src/development/writing_tests.md
new file mode 100644
index 00000000000..8937e0d8e94
--- /dev/null
+++ b/book/src/development/writing_tests.md
@@ -0,0 +1,218 @@
+# Testing
+
+Developing lints for Clippy is a Test-Driven Development (TDD) process because
+our first task before implementing any logic for a new lint is to write some test cases.
+
+## Develop Lints with Tests
+
+When we develop Clippy, we enter a complex and chaotic realm full of
+programmatic issues, stylistic errors, illogical code and non-adherence to convention.
+Tests are the first layer of order we can leverage to define when and where
+we want a new lint to trigger or not.
+
+Moreover, writing tests first help Clippy developers to find a balance for
+the first iteration of and further enhancements for a lint.
+With test cases on our side, we will not have to worry about over-engineering
+a lint on its first version nor missing out some obvious edge cases of the lint.
+This approach empowers us to iteratively enhance each lint.
+
+## Clippy UI Tests
+
+We use **UI tests** for testing in Clippy. These UI tests check that the output
+of Clippy is exactly as we expect it to be. Each test is just a plain Rust file
+that contains the code we want to check.
+
+The output of Clippy is compared against a `.stderr` file. Note that you don't
+have to create this file yourself. We'll get to generating the `.stderr` files
+with the command [`cargo bless`](#cargo-bless) (seen later on).
+
+### Write Test Cases
+
+Let us now think about some tests for our imaginary `foo_functions` lint. We
+start by opening the test file `tests/ui/foo_functions.rs` that was created by
+`cargo dev new_lint`.
+
+Update the file with some examples to get started:
+
+```rust
+#![warn(clippy::foo_functions)] // < Add this, so the lint is guaranteed to be enabled in this file
+
+// Impl methods
+struct A;
+impl A {
+    pub fn fo(&self) {}
+    pub fn foo(&self) {} //~ ERROR: function called "foo"
+    pub fn food(&self) {}
+}
+
+// Default trait methods
+trait B {
+    fn fo(&self) {}
+    fn foo(&self) {} //~ ERROR: function called "foo"
+    fn food(&self) {}
+}
+
+// Plain functions
+fn fo() {}
+fn foo() {} //~ ERROR: function called "foo"
+fn food() {}
+
+fn main() {
+    // We also don't want to lint method calls
+    foo();
+    let a = A;
+    a.foo();
+}
+```
+
+Without actual lint logic to emit the lint when we see a `foo` function name,
+this test will just pass, because no lint will be emitted. However, we can now
+run the test with the following command:
+
+```sh
+$ TESTNAME=foo_functions cargo uitest
+```
+
+Clippy will compile and it will conclude with an `ok` for the tests:
+
+```
+...Clippy warnings and test outputs...
+test compile_test ... ok
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.48s
+```
+
+This is normal. After all, we wrote a bunch of Rust code but we haven't really
+implemented any logic for Clippy to detect `foo` functions and emit a lint.
+
+As we gradually implement our lint logic, we will keep running this UI test command.
+Clippy will begin outputting information that allows us to check if the output is
+turning into what we want it to be.
+
+### Example output
+
+As our `foo_functions` lint is tested, the output would look something like this:
+
+```
+failures:
+---- compile_test stdout ----
+normalized stderr:
+error: function called "foo"
+  --> $DIR/foo_functions.rs:6:12
+   |
+LL |     pub fn foo(&self) {}
+   |            ^^^
+   |
+   = note: `-D clippy::foo-functions` implied by `-D warnings`
+error: function called "foo"
+  --> $DIR/foo_functions.rs:13:8
+   |
+LL |     fn foo(&self) {}
+   |        ^^^
+error: function called "foo"
+  --> $DIR/foo_functions.rs:19:4
+   |
+LL | fn foo() {}
+   |    ^^^
+error: aborting due to 3 previous errors
+```
+
+Note the *failures* label at the top of the fragment, we'll get rid of it
+(saving this output) in the next section.
+
+> _Note:_ You can run multiple test files by specifying a comma separated list:
+> `TESTNAME=foo_functions,bar_methods,baz_structs`.
+
+### `cargo bless`
+
+Once we are satisfied with the output, we need to run this command to
+generate or update the `.stderr` file for our lint:
+
+```sh
+$ TESTNAME=foo_functions cargo uibless
+```
+
+This writes the emitted lint suggestions and fixes to the `.stderr` file, with
+the reason for the lint, suggested fixes, and line numbers, etc.
+
+Running `TESTNAME=foo_functions cargo uitest` should pass then. When we commit
+our lint, we need to commit the generated `.stderr` files, too.
+
+In general, you should only commit files changed by `cargo bless` for the
+specific lint you are creating/editing.
+
+> _Note:_ If the generated `.stderr`, and `.fixed` files are empty,
+> they should be removed.
+
+## `toml` Tests
+
+Some lints can be configured through a `clippy.toml` file. Those configuration
+values are tested in `tests/ui-toml`.
+
+To add a new test there, create a new directory and add the files:
+
+- `clippy.toml`: Put here the configuration value you want to test.
+- `lint_name.rs`: A test file where you put the testing code, that should see a
+  different lint behavior according to the configuration set in the
+  `clippy.toml` file.
+
+The potential `.stderr` and `.fixed` files can again be generated with `cargo
+bless`.
+
+## Cargo Lints
+
+The process of testing is different for Cargo lints in that now we are
+interested in the `Cargo.toml` manifest file. In this case, we also need a
+minimal crate associated with that manifest. Those tests are generated in
+`tests/ui-cargo`.
+
+Imagine we have a new example lint that is named `foo_categories`, we can run:
+
+```sh
+$ cargo dev new_lint --name=foo_categories --pass=late --category=cargo
+```
+
+After running `cargo dev new_lint` we will find by default two new crates,
+each with its manifest file:
+
+* `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the
+  new lint to raise an error.
+* `tests/ui-cargo/foo_categories/pass/Cargo.toml`: this file should not trigger
+  the lint.
+
+If you need more cases, you can copy one of those crates (under
+`foo_categories`) and rename it.
+
+The process of generating the `.stderr` file is the same as for other lints
+and prepending the `TESTNAME` variable to `cargo uitest` works for Cargo lints too.
+
+## Rustfix Tests
+
+If the lint you are working on is making use of structured suggestions,
+[`rustfix`] will apply the suggestions from the lint to the test file code and
+compare that to the contents of a `.fixed` file.
+
+Structured suggestions tell a user how to fix or re-write certain code that has
+been linted with [`span_lint_and_sugg`].
+
+Should `span_lint_and_sugg` be used to generate a suggestion, but not all
+suggestions lead to valid code, you can use the `//@no-rustfix` comment on top
+of the test file, to not run `rustfix` on that file.
+
+We'll talk about suggestions more in depth in a [later chapter](emitting_lints.md).
+
+Use `cargo bless` to automatically generate the `.fixed` file after running
+the tests.
+
+[`rustfix`]: https://github.com/rust-lang/rustfix
+[`span_lint_and_sugg`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_sugg.html
+
+## Testing Manually
+
+Manually testing against an example file can be useful if you have added some
+`println!`s and the test suite output becomes unreadable.
+
+To try Clippy with your local modifications, run from the working copy root.
+
+```sh
+$ cargo dev lint input.rs
+```
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index caaad6d1173..52c795e04fe 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -751,3 +751,27 @@ Which crates to allow absolute paths from
 * [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths)
 
 
+## `enforce-iter-loop-reborrow`
+#### Example
+```
+let mut vec = vec![1, 2, 3];
+let rmvec = &mut vec;
+for _ in rmvec.iter() {}
+for _ in rmvec.iter_mut() {}
+```
+
+Use instead:
+```
+let mut vec = vec![1, 2, 3];
+let rmvec = &mut vec;
+for _ in &*rmvec {}
+for _ in &mut *rmvec {}
+```
+
+**Default Value:** `false` (`bool`)
+
+---
+**Affected lints:**
+* [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop)
+
+
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index f73f1ed18f8..a4d40df52e7 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -211,8 +211,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
     crate::implied_bounds_in_impls::IMPLIED_BOUNDS_IN_IMPLS_INFO,
     crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
-    crate::incorrect_impls::INCORRECT_CLONE_IMPL_ON_COPY_TYPE_INFO,
-    crate::incorrect_impls::INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE_INFO,
     crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO,
     crate::indexing_slicing::INDEXING_SLICING_INFO,
     crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO,
@@ -365,6 +363,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::ITER_NTH_ZERO_INFO,
     crate::methods::ITER_ON_EMPTY_COLLECTIONS_INFO,
     crate::methods::ITER_ON_SINGLE_ITEMS_INFO,
+    crate::methods::ITER_OUT_OF_BOUNDS_INFO,
     crate::methods::ITER_OVEREAGER_CLONED_INFO,
     crate::methods::ITER_SKIP_NEXT_INFO,
     crate::methods::ITER_SKIP_ZERO_INFO,
@@ -456,6 +455,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::misc_early::ZERO_PREFIXED_LITERAL_INFO,
     crate::mismatching_type_param_order::MISMATCHING_TYPE_PARAM_ORDER_INFO,
     crate::missing_assert_message::MISSING_ASSERT_MESSAGE_INFO,
+    crate::missing_asserts_for_indexing::MISSING_ASSERTS_FOR_INDEXING_INFO,
     crate::missing_const_for_fn::MISSING_CONST_FOR_FN_INFO,
     crate::missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS_INFO,
     crate::missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES_INFO,
@@ -496,6 +496,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::no_effect::NO_EFFECT_UNDERSCORE_BINDING_INFO,
     crate::no_effect::UNNECESSARY_OPERATION_INFO,
     crate::no_mangle_with_rust_abi::NO_MANGLE_WITH_RUST_ABI_INFO,
+    crate::non_canonical_impls::NON_CANONICAL_CLONE_IMPL_INFO,
+    crate::non_canonical_impls::NON_CANONICAL_PARTIAL_ORD_IMPL_INFO,
     crate::non_copy_const::BORROW_INTERIOR_MUTABLE_CONST_INFO,
     crate::non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST_INFO,
     crate::non_expressive_names::JUST_UNDERSCORES_AND_DIGITS_INFO,
diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs
index 03b5a2d6d08..bbce6e1dd8f 100644
--- a/clippy_lints/src/default_union_representation.rs
+++ b/clippy_lints/src/default_union_representation.rs
@@ -69,6 +69,9 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
 }
 
 /// Returns true if the given item is a union with at least two non-ZST fields.
+/// (ZST fields having an arbitrary offset is completely inconsequential, and
+/// if there is only one field left after ignoring ZST fields then the offset
+/// of that field does not matter either.)
 fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
     if let ItemKind::Union(data, _) = &item.kind {
         data.fields().iter().filter(|f| !is_zst(cx, f.ty)).count() >= 2
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index 58c27855000..8090f821d1f 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -3,7 +3,7 @@ use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exact
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::ty::{is_copy, peel_mid_ty_refs};
+use clippy_utils::ty::{implements_trait, is_copy, peel_mid_ty_refs};
 use clippy_utils::{
     expr_use_ctxt, get_parent_expr, get_parent_node, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode,
 };
@@ -33,7 +33,6 @@ use rustc_middle::ty::{
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
-use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{Obligation, ObligationCause};
 use std::collections::VecDeque;
@@ -452,13 +451,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                                         // Trait methods taking `self`
                                         arg_ty
                                     } && impl_ty.is_ref()
-                                    && cx.tcx.infer_ctxt().build()
-                                        .type_implements_trait(
-                                            trait_id,
-                                            [impl_ty.into()].into_iter().chain(args.iter().copied()),
-                                            cx.param_env,
-                                        )
-                                        .must_apply_modulo_regions()
+                                    && implements_trait(
+                                        cx,
+                                        impl_ty,
+                                        trait_id,
+                                        &args[..cx.tcx.generics_of(trait_id).params.len() - 1],
+                                    )
                                 {
                                     false
                                 } else {
@@ -609,12 +607,14 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             adjusted_ty,
                         },
                     ));
-                } else if stability.is_deref_stable() {
+                } else if stability.is_deref_stable()
+                    && let Some(parent) = get_parent_expr(cx, expr)
+                {
                     self.state = Some((
                         State::ExplicitDeref { mutability: None },
                         StateData {
-                            span: expr.span,
-                            hir_id: expr.hir_id,
+                            span: parent.span,
+                            hir_id: parent.hir_id,
                             adjusted_ty,
                         },
                     ));
@@ -1399,6 +1399,13 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
                 return;
             }
 
+            if let ExprKind::Field(parent_expr, _) = expr.kind
+                && let ty::Adt(adt, _) = cx.typeck_results().expr_ty(parent_expr).kind()
+                && adt.is_union()
+            {
+                // Auto deref does not apply on union field
+                return;
+            }
             span_lint_hir_and_then(
                 cx,
                 EXPLICIT_AUTO_DEREF,
diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs
index 9a85cc4ce2d..d2bfc4f8e27 100644
--- a/clippy_lints/src/derivable_impls.rs
+++ b/clippy_lints/src/derivable_impls.rs
@@ -217,8 +217,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             if let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind();
             if let attrs = cx.tcx.hir().attrs(item.hir_id());
             if !attrs.iter().any(|attr| attr.doc_str().is_some());
-            if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
-            if !child_attrs.iter().any(|attr| attr.doc_str().is_some());
+            if cx.tcx.hir().attrs(impl_item_hir).is_empty();
 
             then {
                 if adt_def.is_struct() {
diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs
index 1971cab64ef..7469f813ef8 100644
--- a/clippy_lints/src/disallowed_macros.rs
+++ b/clippy_lints/src/disallowed_macros.rs
@@ -1,8 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::macro_backtrace;
+use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefIdMap;
-use rustc_hir::{Expr, ForeignItem, HirId, ImplItem, Item, Pat, Path, Stmt, TraitItem, Ty};
+use rustc_hir::{Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, Pat, Path, Stmt, TraitItem, Ty};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{ExpnId, Span};
@@ -111,6 +112,10 @@ impl LateLintPass<'_> for DisallowedMacros {
 
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         self.check(cx, expr.span);
+        // `$t + $t` can have the context of $t, check also the span of the binary operator
+        if let ExprKind::Binary(op, ..) = expr.kind {
+            self.check(cx, op.span);
+        }
     }
 
     fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
@@ -147,4 +152,8 @@ impl LateLintPass<'_> for DisallowedMacros {
     fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, _: HirId) {
         self.check(cx, path.span);
     }
+
+    fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &Attribute) {
+        self.check(cx, attr.span);
+    }
 }
diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index d8f2fbcea00..4498e9ccdec 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -472,7 +472,7 @@ struct DocHeaders {
 
 fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[Attribute]) -> Option<DocHeaders> {
     /// We don't want the parser to choke on intra doc links. Since we don't
-    /// actually care about rendering them, just pretend that all broken links are
+    /// actually care about rendering them, just pretend that all broken links
     /// point to a fake address.
     #[expect(clippy::unnecessary_wraps)] // we're following a type signature
     fn fake_broken_link_callback<'a>(_: BrokenLink<'_>) -> Option<(CowStr<'a>, CowStr<'a>)> {
diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs
index ab6ad3f3b3a..e2d19e24557 100644
--- a/clippy_lints/src/if_then_some_else_none.rs
+++ b/clippy_lints/src/if_then_some_else_none.rs
@@ -6,7 +6,7 @@ use clippy_utils::sugg::Sugg;
 use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
-use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
+use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
             && then_expr.span.ctxt() == ctxt
             && is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
             && is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
-            && !stmts_contains_early_return(then_block.stmts)
+            && !contains_return(then_block.stmts)
         {
             let mut app = Applicability::Unspecified;
             let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app).maybe_par().to_string();
@@ -116,17 +116,3 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
 
     extract_msrv_attr!(LateContext);
 }
-
-fn stmts_contains_early_return(stmts: &[Stmt<'_>]) -> bool {
-    stmts.iter().any(|stmt| {
-        let Stmt {
-            kind: StmtKind::Semi(e),
-            ..
-        } = stmt
-        else {
-            return false;
-        };
-
-        contains_return(e)
-    })
-}
diff --git a/clippy_lints/src/ignored_unit_patterns.rs b/clippy_lints/src/ignored_unit_patterns.rs
index c635120b882..d8ead1c9d9f 100644
--- a/clippy_lints/src/ignored_unit_patterns.rs
+++ b/clippy_lints/src/ignored_unit_patterns.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use hir::PatKind;
+use hir::{Node, PatKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
@@ -37,6 +37,17 @@ declare_lint_pass!(IgnoredUnitPatterns => [IGNORED_UNIT_PATTERNS]);
 
 impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns {
     fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
+        match cx.tcx.hir().get_parent(pat.hir_id) {
+            Node::Param(param) if matches!(cx.tcx.hir().get_parent(param.hir_id), Node::Item(_)) => {
+                // Ignore function parameters
+                return;
+            },
+            Node::Local(local) if local.ty.is_some() => {
+                // Ignore let bindings with explicit type
+                return;
+            },
+            _ => {},
+        }
         if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).is_unit() {
             span_lint_and_sugg(
                 cx,
diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs
index c6d1acad3a0..ec9044bba5c 100644
--- a/clippy_lints/src/implied_bounds_in_impls.rs
+++ b/clippy_lints/src/implied_bounds_in_impls.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use rustc_errors::{Applicability, SuggestionStyle};
-use rustc_hir::def_id::LocalDefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     Body, FnDecl, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, ItemKind, TraitBoundModifier, TraitItem,
@@ -9,7 +9,7 @@ use rustc_hir::{
 };
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, ClauseKind, TyCtxt};
+use rustc_middle::ty::{self, ClauseKind, Generics, Ty, TyCtxt};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
 
@@ -45,52 +45,169 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.73.0"]
     pub IMPLIED_BOUNDS_IN_IMPLS,
-    complexity,
+    nursery,
     "specifying bounds that are implied by other bounds in `impl Trait` type"
 }
 declare_lint_pass!(ImpliedBoundsInImpls => [IMPLIED_BOUNDS_IN_IMPLS]);
 
-/// This function tries to, for all type parameters in a supertype predicate `GenericTrait<U>`,
-/// check if the substituted type in the implied-by bound matches with what's subtituted in the
-/// implied type.
+#[allow(clippy::too_many_arguments)]
+fn emit_lint(
+    cx: &LateContext<'_>,
+    poly_trait: &rustc_hir::PolyTraitRef<'_>,
+    opaque_ty: &rustc_hir::OpaqueTy<'_>,
+    index: usize,
+    // The bindings that were implied
+    implied_bindings: &[rustc_hir::TypeBinding<'_>],
+    // The original bindings that `implied_bindings` are implied from
+    implied_by_bindings: &[rustc_hir::TypeBinding<'_>],
+    implied_by_args: &[GenericArg<'_>],
+    implied_by_span: Span,
+) {
+    let implied_by = snippet(cx, implied_by_span, "..");
+
+    span_lint_and_then(
+        cx,
+        IMPLIED_BOUNDS_IN_IMPLS,
+        poly_trait.span,
+        &format!("this bound is already specified as the supertrait of `{implied_by}`"),
+        |diag| {
+            // If we suggest removing a bound, we may also need to extend the span
+            // to include the `+` token that is ahead or behind,
+            // so we don't end up with something like `impl + B` or `impl A + `
+
+            let implied_span_extended = if let Some(next_bound) = opaque_ty.bounds.get(index + 1) {
+                poly_trait.span.to(next_bound.span().shrink_to_lo())
+            } else if index > 0
+                && let Some(prev_bound) = opaque_ty.bounds.get(index - 1)
+            {
+                prev_bound.span().shrink_to_hi().to(poly_trait.span.shrink_to_hi())
+            } else {
+                poly_trait.span
+            };
+
+            let mut sugg = vec![(implied_span_extended, String::new())];
+
+            // We also might need to include associated type binding that were specified in the implied bound,
+            // but omitted in the implied-by bound:
+            // `fn f() -> impl Deref<Target = u8> + DerefMut`
+            // If we're going to suggest removing `Deref<..>`, we'll need to put `<Target = u8>` on `DerefMut`
+            let omitted_assoc_tys: Vec<_> = implied_bindings
+                .iter()
+                .filter(|binding| !implied_by_bindings.iter().any(|b| b.ident == binding.ident))
+                .collect();
+
+            if !omitted_assoc_tys.is_empty() {
+                // `<>` needs to be added if there aren't yet any generic arguments or bindings
+                let needs_angle_brackets = implied_by_args.is_empty() && implied_by_bindings.is_empty();
+                let insert_span = match (implied_by_args, implied_by_bindings) {
+                    ([.., arg], [.., binding]) => arg.span().max(binding.span).shrink_to_hi(),
+                    ([.., arg], []) => arg.span().shrink_to_hi(),
+                    ([], [.., binding]) => binding.span.shrink_to_hi(),
+                    ([], []) => implied_by_span.shrink_to_hi(),
+                };
+
+                let mut associated_tys_sugg = if needs_angle_brackets {
+                    "<".to_owned()
+                } else {
+                    // If angle brackets aren't needed (i.e., there are already generic arguments or bindings),
+                    // we need to add a comma:
+                    // `impl A<B, C >`
+                    //             ^ if we insert `Assoc=i32` without a comma here, that'd be invalid syntax:
+                    // `impl A<B, C Assoc=i32>`
+                    ", ".to_owned()
+                };
+
+                for (index, binding) in omitted_assoc_tys.into_iter().enumerate() {
+                    if index > 0 {
+                        associated_tys_sugg += ", ";
+                    }
+                    associated_tys_sugg += &snippet(cx, binding.span, "..");
+                }
+                if needs_angle_brackets {
+                    associated_tys_sugg += ">";
+                }
+                sugg.push((insert_span, associated_tys_sugg));
+            }
+
+            diag.multipart_suggestion_with_style(
+                "try removing this bound",
+                sugg,
+                Applicability::MachineApplicable,
+                SuggestionStyle::ShowAlways,
+            );
+        },
+    );
+}
+
+/// Tries to "resolve" a type.
+/// The index passed to this function must start with `Self=0`, i.e. it must be a valid
+/// type parameter index.
+/// If the index is out of bounds, it means that the generic parameter has a default type.
+fn try_resolve_type<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    args: &'tcx [GenericArg<'tcx>],
+    generics: &'tcx Generics,
+    index: usize,
+) -> Option<Ty<'tcx>> {
+    match args.get(index - 1) {
+        Some(GenericArg::Type(ty)) => Some(hir_ty_to_ty(tcx, ty)),
+        Some(_) => None,
+        None => Some(tcx.type_of(generics.params[index].def_id).skip_binder()),
+    }
+}
+
+/// This function tries to, for all generic type parameters in a supertrait predicate `trait ...<U>:
+/// GenericTrait<U>`, check if the substituted type in the implied-by bound matches with what's
+/// subtituted in the implied bound.
 ///
 /// Consider this example.
 /// ```rust,ignore
 /// trait GenericTrait<T> {}
 /// trait GenericSubTrait<T, U, V>: GenericTrait<U> {}
-///                                              ^ trait_predicate_args: [Self#0, U#2]
+///                                 ^^^^^^^^^^^^^^^ trait_predicate_args: [Self#0, U#2]
+///                                                 (the Self#0 is implicit: `<Self as GenericTrait<U>>`)
 /// impl GenericTrait<i32> for () {}
 /// impl GenericSubTrait<(), i32, ()> for () {}
-/// impl GenericSubTrait<(), [u8; 8], ()> for () {}
+/// impl GenericSubTrait<(), i64, ()> for () {}
 ///
-/// fn f() -> impl GenericTrait<i32> + GenericSubTrait<(), [u8; 8], ()> {
-///                             ^^^ implied_args       ^^^^^^^^^^^^^^^ implied_by_args
-///                                                                    (we are interested in `[u8; 8]` specifically, as that
-///                                                                     is what `U` in `GenericTrait<U>` is substituted with)
-///     ()
+/// fn f() -> impl GenericTrait<i32> + GenericSubTrait<(), i64, ()> {
+///                             ^^^ implied_args       ^^^^^^^^^^^ implied_by_args
+///                                                                (we are interested in `i64` specifically, as that
+///                                                                 is what `U` in `GenericTrait<U>` is substituted with)
 /// }
 /// ```
-/// Here i32 != [u8; 8], so this will return false.
-fn is_same_generics(
-    tcx: TyCtxt<'_>,
-    trait_predicate_args: &[ty::GenericArg<'_>],
-    implied_by_args: &[GenericArg<'_>],
-    implied_args: &[GenericArg<'_>],
+/// Here i32 != i64, so this will return false.
+fn is_same_generics<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_predicate_args: &'tcx [ty::GenericArg<'tcx>],
+    implied_by_args: &'tcx [GenericArg<'tcx>],
+    implied_args: &'tcx [GenericArg<'tcx>],
+    implied_by_def_id: DefId,
+    implied_def_id: DefId,
 ) -> bool {
+    // Get the generics of the two traits to be able to get default generic parameter.
+    let implied_by_generics = tcx.generics_of(implied_by_def_id);
+    let implied_generics = tcx.generics_of(implied_def_id);
+
     trait_predicate_args
         .iter()
         .enumerate()
         .skip(1) // skip `Self` implicit arg
         .all(|(arg_index, arg)| {
-            if let Some(ty) = arg.as_type()
-                && let &ty::Param(ty::ParamTy{ index, .. }) = ty.kind()
-                // Since `trait_predicate_args` and type params in traits start with `Self=0`
-                // and generic argument lists `GenericTrait<i32>` don't have `Self`,
-                // we need to subtract 1 from the index.
-                && let GenericArg::Type(ty_a) = implied_by_args[index as usize - 1]
-                && let GenericArg::Type(ty_b) = implied_args[arg_index - 1]
-            {
-                hir_ty_to_ty(tcx, ty_a) == hir_ty_to_ty(tcx, ty_b)
+            if let Some(ty) = arg.as_type() {
+                if let &ty::Param(ty::ParamTy { index, .. }) = ty.kind()
+                    // `index == 0` means that it's referring to `Self`,
+                    // in which case we don't try to substitute it
+                    && index != 0
+                    && let Some(ty_a) = try_resolve_type(tcx, implied_by_args, implied_by_generics, index as usize)
+                    && let Some(ty_b) = try_resolve_type(tcx, implied_args, implied_generics, arg_index)
+                {
+                    ty_a == ty_b
+                } else if let Some(ty_b) = try_resolve_type(tcx, implied_args, implied_generics, arg_index) {
+                    ty == ty_b
+                } else {
+                    false
+                }
             } else {
                 false
             }
@@ -121,7 +238,7 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
                 && let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates
                 && !predicates.is_empty() // If the trait has no supertrait, there is nothing to add.
             {
-                Some((bound.span(), path.args.map_or([].as_slice(), |a| a.args), predicates))
+                Some((bound.span(), path, predicates, trait_def_id))
             } else {
                 None
             }
@@ -134,43 +251,42 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
             if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound
                 && let [.., path] = poly_trait.trait_ref.path.segments
                 && let implied_args = path.args.map_or([].as_slice(), |a| a.args)
+                && let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings)
                 && let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id()
-                && let Some(implied_by_span) = implied_bounds.iter().find_map(|&(span, implied_by_args, preds)| {
-                    preds.iter().find_map(|(clause, _)| {
-                        if let ClauseKind::Trait(tr) = clause.kind().skip_binder()
-                            && tr.def_id() == def_id
-                            && is_same_generics(cx.tcx, tr.trait_ref.args, implied_by_args, implied_args)
-                        {
-                            Some(span)
-                        } else {
-                            None
-                        }
+                && let Some((implied_by_span, implied_by_args, implied_by_bindings)) = implied_bounds
+                    .iter()
+                    .find_map(|&(span, implied_by_path, preds, implied_by_def_id)| {
+                        let implied_by_args = implied_by_path.args.map_or([].as_slice(), |a| a.args);
+                        let implied_by_bindings = implied_by_path.args.map_or([].as_slice(), |a| a.bindings);
+
+                        preds.iter().find_map(|(clause, _)| {
+                            if let ClauseKind::Trait(tr) = clause.kind().skip_binder()
+                                && tr.def_id() == def_id
+                                && is_same_generics(
+                                    cx.tcx,
+                                    tr.trait_ref.args,
+                                    implied_by_args,
+                                    implied_args,
+                                    implied_by_def_id,
+                                    def_id,
+                                )
+                            {
+                                Some((span, implied_by_args, implied_by_bindings))
+                            } else {
+                                None
+                            }
+                        })
                     })
-                })
             {
-                let implied_by = snippet(cx, implied_by_span, "..");
-                span_lint_and_then(
-                    cx, IMPLIED_BOUNDS_IN_IMPLS,
-                    poly_trait.span,
-                    &format!("this bound is already specified as the supertrait of `{implied_by}`"),
-                    |diag| {
-                        // If we suggest removing a bound, we may also need extend the span
-                        // to include the `+` token, so we don't end up with something like `impl + B`
-
-                        let implied_span_extended = if let Some(next_bound) = opaque_ty.bounds.get(index + 1) {
-                            poly_trait.span.to(next_bound.span().shrink_to_lo())
-                        } else {
-                            poly_trait.span
-                        };
-
-                        diag.span_suggestion_with_style(
-                            implied_span_extended,
-                            "try removing this bound",
-                            "",
-                            Applicability::MachineApplicable,
-                            SuggestionStyle::ShowAlways
-                        );
-                    }
+                emit_lint(
+                    cx,
+                    poly_trait,
+                    opaque_ty,
+                    index,
+                    implied_bindings,
+                    implied_by_bindings,
+                    implied_by_args,
+                    implied_by_span
                 );
             }
         }
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 20fdf26dc52..f52614b6208 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -156,7 +156,6 @@ mod implicit_saturating_add;
 mod implicit_saturating_sub;
 mod implied_bounds_in_impls;
 mod inconsistent_struct_constructor;
-mod incorrect_impls;
 mod index_refutable_slice;
 mod indexing_slicing;
 mod infinite_iter;
@@ -212,6 +211,7 @@ mod misc;
 mod misc_early;
 mod mismatching_type_param_order;
 mod missing_assert_message;
+mod missing_asserts_for_indexing;
 mod missing_const_for_fn;
 mod missing_doc;
 mod missing_enforced_import_rename;
@@ -245,6 +245,7 @@ mod neg_multiply;
 mod new_without_default;
 mod no_effect;
 mod no_mangle_with_rust_abi;
+mod non_canonical_impls;
 mod non_copy_const;
 mod non_expressive_names;
 mod non_octal_unix_permissions;
@@ -697,7 +698,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     store.register_late_pass(|_| Box::<shadow::Shadow>::default());
     store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
-    store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv())));
+    let enforce_iter_loop_reborrow = conf.enforce_iter_loop_reborrow;
+    store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv(), enforce_iter_loop_reborrow)));
     store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
     store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
     store.register_late_pass(|_| Box::new(entry::HashMapPass));
@@ -1070,7 +1072,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             avoid_breaking_exported_api,
         ))
     });
-    store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls));
+    store.register_late_pass(|_| Box::new(non_canonical_impls::NonCanonicalImpls));
     store.register_late_pass(move |_| {
         Box::new(single_call_fn::SingleCallFn {
             avoid_breaking_exported_api,
@@ -1101,6 +1103,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(ignored_unit_patterns::IgnoredUnitPatterns));
     store.register_late_pass(|_| Box::<reserve_after_initialization::ReserveAfterInitialization>::default());
     store.register_late_pass(|_| Box::new(implied_bounds_in_impls::ImpliedBoundsInImpls));
+    store.register_late_pass(|_| Box::new(missing_asserts_for_indexing::MissingAssertsForIndexing));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs
index 7b8c88235a9..6ab256ef001 100644
--- a/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -13,8 +13,14 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMut
 use rustc_middle::ty::{self, EarlyBinder, Ty, TypeAndMut};
 use rustc_span::sym;
 
-pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, msrv: &Msrv) {
-    let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr) else {
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    self_arg: &Expr<'_>,
+    call_expr: &Expr<'_>,
+    msrv: &Msrv,
+    enforce_iter_loop_reborrow: bool,
+) {
+    let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow) else {
         return;
     };
     if let ty::Array(_, count) = *ty.peel_refs().kind() {
@@ -102,6 +108,7 @@ fn is_ref_iterable<'tcx>(
     cx: &LateContext<'tcx>,
     self_arg: &Expr<'_>,
     call_expr: &Expr<'_>,
+    enforce_iter_loop_reborrow: bool,
 ) -> Option<(AdjustKind, Ty<'tcx>)> {
     let typeck = cx.typeck_results();
     if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
@@ -142,7 +149,8 @@ fn is_ref_iterable<'tcx>(
                 {
                     return Some((AdjustKind::None, self_ty));
                 }
-            } else if let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind()
+            } else if enforce_iter_loop_reborrow
+                && let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind()
                 && let Some(mutbl) = mutbl
             {
                 // Attempt to reborrow the mutable reference
@@ -186,7 +194,8 @@ fn is_ref_iterable<'tcx>(
                 },
                 ..
             ] => {
-                if target != self_ty
+                if enforce_iter_loop_reborrow
+                    && target != self_ty
                     && implements_trait(cx, target, trait_id, &[])
                     && let Some(ty) =
                         make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs
index ffd29ab7630..1fb16adad7a 100644
--- a/clippy_lints/src/loops/mod.rs
+++ b/clippy_lints/src/loops/mod.rs
@@ -609,10 +609,14 @@ declare_clippy_lint! {
 
 pub struct Loops {
     msrv: Msrv,
+    enforce_iter_loop_reborrow: bool,
 }
 impl Loops {
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(msrv: Msrv, enforce_iter_loop_reborrow: bool) -> Self {
+        Self {
+            msrv,
+            enforce_iter_loop_reborrow,
+        }
     }
 }
 impl_lint_pass!(Loops => [
@@ -719,7 +723,7 @@ impl Loops {
         if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
             match method.ident.as_str() {
                 "iter" | "iter_mut" => {
-                    explicit_iter_loop::check(cx, self_arg, arg, &self.msrv);
+                    explicit_iter_loop::check(cx, self_arg, arg, &self.msrv, self.enforce_iter_loop_reborrow);
                 },
                 "into_iter" => {
                     explicit_into_iter_loop::check(cx, self_arg, arg);
diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index cc19ac55e5e..3d8a4cd948a 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/clippy_lints/src/loops/never_loop.rs
@@ -1,13 +1,13 @@
 use super::utils::make_iterator_snippet;
 use super::NEVER_LOOP;
-use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::ForLoop;
+use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
 use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
 use rustc_lint::LateContext;
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 use std::iter::{once, Iterator};
 
 pub(super) fn check<'tcx>(
@@ -18,7 +18,7 @@ pub(super) fn check<'tcx>(
     for_loop: Option<&ForLoop<'_>>,
 ) {
     match never_loop_block(cx, block, &mut Vec::new(), loop_id) {
-        NeverLoopResult::AlwaysBreak => {
+        NeverLoopResult::Diverging => {
             span_lint_and_then(cx, NEVER_LOOP, span, "this loop never actually loops", |diag| {
                 if let Some(ForLoop {
                     arg: iterator,
@@ -39,67 +39,76 @@ pub(super) fn check<'tcx>(
                 }
             });
         },
-        NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
-        NeverLoopResult::IgnoreUntilEnd(_) => unreachable!(),
+        NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Normal => (),
     }
 }
 
+/// The `never_loop` analysis keeps track of three things:
+///
+/// * Has any (reachable) code path hit a `continue` of the main loop?
+/// * Is the current code path diverging (that is, the next expression is not reachable)
+/// * For each block label `'a` inside the main loop, has any (reachable) code path encountered a
+///   `break 'a`?
+///
+/// The first two bits of information are in this enum, and the last part is in the
+/// `local_labels` variable, which contains a list of `(block_id, reachable)` pairs ordered by
+/// scope.
 #[derive(Copy, Clone)]
 enum NeverLoopResult {
-    // A break/return always get triggered but not necessarily for the main loop.
-    AlwaysBreak,
-    // A continue may occur for the main loop.
+    /// A continue may occur for the main loop.
     MayContinueMainLoop,
-    // Ignore everything until the end of the block with this id
-    IgnoreUntilEnd(HirId),
-    Otherwise,
+    /// We have not encountered any main loop continue,
+    /// but we are diverging (subsequent control flow is not reachable)
+    Diverging,
+    /// We have not encountered any main loop continue,
+    /// and subsequent control flow is (possibly) reachable
+    Normal,
 }
 
 #[must_use]
 fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult {
     match arg {
-        NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise,
+        NeverLoopResult::Diverging | NeverLoopResult::Normal => NeverLoopResult::Normal,
         NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop,
-        NeverLoopResult::IgnoreUntilEnd(id) => NeverLoopResult::IgnoreUntilEnd(id),
     }
 }
 
 // Combine two results for parts that are called in order.
 #[must_use]
-fn combine_seq(first: NeverLoopResult, second: NeverLoopResult) -> NeverLoopResult {
+fn combine_seq(first: NeverLoopResult, second: impl FnOnce() -> NeverLoopResult) -> NeverLoopResult {
     match first {
-        NeverLoopResult::AlwaysBreak | NeverLoopResult::MayContinueMainLoop | NeverLoopResult::IgnoreUntilEnd(_) => {
-            first
-        },
-        NeverLoopResult::Otherwise => second,
+        NeverLoopResult::Diverging | NeverLoopResult::MayContinueMainLoop => first,
+        NeverLoopResult::Normal => second(),
     }
 }
 
+// Combine an iterator of results for parts that are called in order.
+#[must_use]
+fn combine_seq_many(iter: impl IntoIterator<Item = NeverLoopResult>) -> NeverLoopResult {
+    for e in iter {
+        if let NeverLoopResult::Diverging | NeverLoopResult::MayContinueMainLoop = e {
+            return e;
+        }
+    }
+    NeverLoopResult::Normal
+}
+
 // Combine two results where only one of the part may have been executed.
 #[must_use]
-fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult, ignore_ids: &[HirId]) -> NeverLoopResult {
+fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult {
     match (b1, b2) {
-        (NeverLoopResult::IgnoreUntilEnd(a), NeverLoopResult::IgnoreUntilEnd(b)) => {
-            if ignore_ids.iter().find(|&e| e == &a || e == &b).unwrap() == &a {
-                NeverLoopResult::IgnoreUntilEnd(b)
-            } else {
-                NeverLoopResult::IgnoreUntilEnd(a)
-            }
-        },
-        (i @ NeverLoopResult::IgnoreUntilEnd(_), NeverLoopResult::AlwaysBreak)
-        | (NeverLoopResult::AlwaysBreak, i @ NeverLoopResult::IgnoreUntilEnd(_)) => i,
-        (NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
         (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
             NeverLoopResult::MayContinueMainLoop
         },
-        (NeverLoopResult::Otherwise, _) | (_, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise,
+        (NeverLoopResult::Normal, _) | (_, NeverLoopResult::Normal) => NeverLoopResult::Normal,
+        (NeverLoopResult::Diverging, NeverLoopResult::Diverging) => NeverLoopResult::Diverging,
     }
 }
 
 fn never_loop_block<'tcx>(
     cx: &LateContext<'tcx>,
     block: &Block<'tcx>,
-    ignore_ids: &mut Vec<HirId>,
+    local_labels: &mut Vec<(HirId, bool)>,
     main_loop_id: HirId,
 ) -> NeverLoopResult {
     let iter = block
@@ -107,15 +116,21 @@ fn never_loop_block<'tcx>(
         .iter()
         .filter_map(stmt_to_expr)
         .chain(block.expr.map(|expr| (expr, None)));
-
-    iter.map(|(e, els)| {
-        let e = never_loop_expr(cx, e, ignore_ids, main_loop_id);
+    combine_seq_many(iter.map(|(e, els)| {
+        let e = never_loop_expr(cx, e, local_labels, main_loop_id);
         // els is an else block in a let...else binding
         els.map_or(e, |els| {
-            combine_branches(e, never_loop_block(cx, els, ignore_ids, main_loop_id), ignore_ids)
+            combine_seq(e, || match never_loop_block(cx, els, local_labels, main_loop_id) {
+                // Returning MayContinueMainLoop here means that
+                // we will not evaluate the rest of the body
+                NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop,
+                // An else block always diverges, so the Normal case should not happen,
+                // but the analysis is approximate so it might return Normal anyway.
+                // Returning Normal here says that nothing more happens on the main path
+                NeverLoopResult::Diverging | NeverLoopResult::Normal => NeverLoopResult::Normal,
+            })
         })
-    })
-    .fold(NeverLoopResult::Otherwise, combine_seq)
+    }))
 }
 
 fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'tcx Block<'tcx>>)> {
@@ -131,76 +146,69 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t
 fn never_loop_expr<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &Expr<'tcx>,
-    ignore_ids: &mut Vec<HirId>,
+    local_labels: &mut Vec<(HirId, bool)>,
     main_loop_id: HirId,
 ) -> NeverLoopResult {
-    match expr.kind {
+    let result = match expr.kind {
         ExprKind::Unary(_, e)
         | ExprKind::Cast(e, _)
         | ExprKind::Type(e, _)
         | ExprKind::Field(e, _)
         | ExprKind::AddrOf(_, _, e)
         | ExprKind::Repeat(e, _)
-        | ExprKind::DropTemps(e) => never_loop_expr(cx, e, ignore_ids, main_loop_id),
-        ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, ignore_ids, main_loop_id),
-        ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, &mut es.iter(), ignore_ids, main_loop_id),
+        | ExprKind::DropTemps(e) => never_loop_expr(cx, e, local_labels, main_loop_id),
+        ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id),
+        ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id),
         ExprKind::MethodCall(_, receiver, es, _) => never_loop_expr_all(
             cx,
-            &mut std::iter::once(receiver).chain(es.iter()),
-            ignore_ids,
+            std::iter::once(receiver).chain(es.iter()),
+            local_labels,
             main_loop_id,
         ),
         ExprKind::Struct(_, fields, base) => {
-            let fields = never_loop_expr_all(cx, &mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id);
+            let fields = never_loop_expr_all(cx, fields.iter().map(|f| f.expr), local_labels, main_loop_id);
             if let Some(base) = base {
-                combine_seq(fields, never_loop_expr(cx, base, ignore_ids, main_loop_id))
+                combine_seq(fields, || never_loop_expr(cx, base, local_labels, main_loop_id))
             } else {
                 fields
             }
         },
-        ExprKind::Call(e, es) => never_loop_expr_all(cx, &mut once(e).chain(es.iter()), ignore_ids, main_loop_id),
+        ExprKind::Call(e, es) => never_loop_expr_all(cx, once(e).chain(es.iter()), local_labels, main_loop_id),
         ExprKind::Binary(_, e1, e2)
         | ExprKind::Assign(e1, e2, _)
         | ExprKind::AssignOp(_, e1, e2)
-        | ExprKind::Index(e1, e2, _) => {
-            never_loop_expr_all(cx, &mut [e1, e2].iter().copied(), ignore_ids, main_loop_id)
-        },
+        | ExprKind::Index(e1, e2, _) => never_loop_expr_all(cx, [e1, e2].iter().copied(), local_labels, main_loop_id),
         ExprKind::Loop(b, _, _, _) => {
-            // Break can come from the inner loop so remove them.
-            absorb_break(never_loop_block(cx, b, ignore_ids, main_loop_id))
+            // We don't attempt to track reachability after a loop,
+            // just assume there may have been a break somewhere
+            absorb_break(never_loop_block(cx, b, local_labels, main_loop_id))
         },
         ExprKind::If(e, e2, e3) => {
-            let e1 = never_loop_expr(cx, e, ignore_ids, main_loop_id);
-            let e2 = never_loop_expr(cx, e2, ignore_ids, main_loop_id);
-            // If we know the `if` condition evaluates to `true`, don't check everything past it; it
-            // should just return whatever's evaluated for `e1` and `e2` since `e3` is unreachable
-            if let Some(Constant::Bool(true)) = constant(cx, cx.typeck_results(), e) {
-                return combine_seq(e1, e2);
-            }
-            let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| {
-                never_loop_expr(cx, e, ignore_ids, main_loop_id)
-            });
-            combine_seq(e1, combine_branches(e2, e3, ignore_ids))
+            let e1 = never_loop_expr(cx, e, local_labels, main_loop_id);
+            combine_seq(e1, || {
+                let e2 = never_loop_expr(cx, e2, local_labels, main_loop_id);
+                let e3 = e3.as_ref().map_or(NeverLoopResult::Normal, |e| {
+                    never_loop_expr(cx, e, local_labels, main_loop_id)
+                });
+                combine_branches(e2, e3)
+            })
         },
         ExprKind::Match(e, arms, _) => {
-            let e = never_loop_expr(cx, e, ignore_ids, main_loop_id);
-            if arms.is_empty() {
-                e
-            } else {
-                let arms = never_loop_expr_branch(cx, &mut arms.iter().map(|a| a.body), ignore_ids, main_loop_id);
-                combine_seq(e, arms)
-            }
+            let e = never_loop_expr(cx, e, local_labels, main_loop_id);
+            combine_seq(e, || {
+                arms.iter().fold(NeverLoopResult::Diverging, |a, b| {
+                    combine_branches(a, never_loop_expr(cx, b.body, local_labels, main_loop_id))
+                })
+            })
         },
         ExprKind::Block(b, l) => {
             if l.is_some() {
-                ignore_ids.push(b.hir_id);
-            }
-            let ret = never_loop_block(cx, b, ignore_ids, main_loop_id);
-            if l.is_some() {
-                ignore_ids.pop();
+                local_labels.push((b.hir_id, false));
             }
+            let ret = never_loop_block(cx, b, local_labels, main_loop_id);
+            let jumped_to = l.is_some() && local_labels.pop().unwrap().1;
             match ret {
-                NeverLoopResult::IgnoreUntilEnd(a) if a == b.hir_id => NeverLoopResult::Otherwise,
+                NeverLoopResult::Diverging if jumped_to => NeverLoopResult::Normal,
                 _ => ret,
             }
         },
@@ -211,74 +219,78 @@ fn never_loop_expr<'tcx>(
             if id == main_loop_id {
                 NeverLoopResult::MayContinueMainLoop
             } else {
-                NeverLoopResult::AlwaysBreak
+                NeverLoopResult::Diverging
             }
         },
-        // checks if break targets a block instead of a loop
-        ExprKind::Break(Destination { target_id: Ok(t), .. }, e) if ignore_ids.contains(&t) => e
-            .map_or(NeverLoopResult::IgnoreUntilEnd(t), |e| {
-                never_loop_expr(cx, e, ignore_ids, main_loop_id)
-            }),
-        ExprKind::Break(_, e) | ExprKind::Ret(e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| {
-            combine_seq(
-                never_loop_expr(cx, e, ignore_ids, main_loop_id),
-                NeverLoopResult::AlwaysBreak,
-            )
-        }),
-        ExprKind::Become(e) => combine_seq(
-            never_loop_expr(cx, e, ignore_ids, main_loop_id),
-            NeverLoopResult::AlwaysBreak,
-        ),
-        ExprKind::InlineAsm(asm) => asm
-            .operands
-            .iter()
-            .map(|(o, _)| match o {
-                InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
-                    never_loop_expr(cx, expr, ignore_ids, main_loop_id)
-                },
-                InlineAsmOperand::Out { expr, .. } => {
-                    never_loop_expr_all(cx, &mut expr.iter().copied(), ignore_ids, main_loop_id)
-                },
-                InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => never_loop_expr_all(
-                    cx,
-                    &mut once(*in_expr).chain(out_expr.iter().copied()),
-                    ignore_ids,
-                    main_loop_id,
-                ),
-                InlineAsmOperand::Const { .. }
-                | InlineAsmOperand::SymFn { .. }
-                | InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
+        ExprKind::Break(_, e) | ExprKind::Ret(e) => {
+            let first = e.as_ref().map_or(NeverLoopResult::Normal, |e| {
+                never_loop_expr(cx, e, local_labels, main_loop_id)
+            });
+            combine_seq(first, || {
+                // checks if break targets a block instead of a loop
+                if let ExprKind::Break(Destination { target_id: Ok(t), .. }, _) = expr.kind {
+                    if let Some((_, reachable)) = local_labels.iter_mut().find(|(label, _)| *label == t) {
+                        *reachable = true;
+                    }
+                }
+                NeverLoopResult::Diverging
             })
-            .fold(NeverLoopResult::Otherwise, combine_seq),
+        },
+        ExprKind::Become(e) => combine_seq(never_loop_expr(cx, e, local_labels, main_loop_id), || {
+            NeverLoopResult::Diverging
+        }),
+        ExprKind::InlineAsm(asm) => combine_seq_many(asm.operands.iter().map(|(o, _)| match o {
+            InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
+                never_loop_expr(cx, expr, local_labels, main_loop_id)
+            },
+            InlineAsmOperand::Out { expr, .. } => {
+                never_loop_expr_all(cx, expr.iter().copied(), local_labels, main_loop_id)
+            },
+            InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => never_loop_expr_all(
+                cx,
+                once(*in_expr).chain(out_expr.iter().copied()),
+                local_labels,
+                main_loop_id,
+            ),
+            InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } | InlineAsmOperand::SymStatic { .. } => {
+                NeverLoopResult::Normal
+            },
+        })),
         ExprKind::OffsetOf(_, _)
         | ExprKind::Yield(_, _)
         | ExprKind::Closure { .. }
         | ExprKind::Path(_)
         | ExprKind::ConstBlock(_)
         | ExprKind::Lit(_)
-        | ExprKind::Err(_) => NeverLoopResult::Otherwise,
+        | ExprKind::Err(_) => NeverLoopResult::Normal,
+    };
+    let result = combine_seq(result, || {
+        if cx.typeck_results().expr_ty(expr).is_never() {
+            NeverLoopResult::Diverging
+        } else {
+            NeverLoopResult::Normal
+        }
+    });
+    if  let NeverLoopResult::Diverging = result &&
+        let Some(macro_call) = root_macro_call_first_node(cx, expr) &&
+        let Some(sym::todo_macro) = cx.tcx.get_diagnostic_name(macro_call.def_id)
+    {
+        // We return MayContinueMainLoop here because we treat `todo!()`
+        // as potentially containing any code, including a continue of the main loop.
+        // This effectively silences the lint whenever a loop contains this macro anywhere.
+        NeverLoopResult::MayContinueMainLoop
+    } else {
+        result
     }
 }
 
 fn never_loop_expr_all<'tcx, T: Iterator<Item = &'tcx Expr<'tcx>>>(
     cx: &LateContext<'tcx>,
-    es: &mut T,
-    ignore_ids: &mut Vec<HirId>,
+    es: T,
+    local_labels: &mut Vec<(HirId, bool)>,
     main_loop_id: HirId,
 ) -> NeverLoopResult {
-    es.map(|e| never_loop_expr(cx, e, ignore_ids, main_loop_id))
-        .fold(NeverLoopResult::Otherwise, combine_seq)
-}
-
-fn never_loop_expr_branch<'tcx, T: Iterator<Item = &'tcx Expr<'tcx>>>(
-    cx: &LateContext<'tcx>,
-    e: &mut T,
-    ignore_ids: &mut Vec<HirId>,
-    main_loop_id: HirId,
-) -> NeverLoopResult {
-    e.fold(NeverLoopResult::AlwaysBreak, |a, b| {
-        combine_branches(a, never_loop_expr(cx, b, ignore_ids, main_loop_id), ignore_ids)
-    })
+    combine_seq_many(es.map(|e| never_loop_expr(cx, e, local_labels, main_loop_id)))
 }
 
 fn for_to_if_let_sugg(cx: &LateContext<'_>, iterator: &Expr<'_>, pat: &Pat<'_>) -> String {
diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs
index 39d8b20d38d..90557b55560 100644
--- a/clippy_lints/src/manual_range_patterns.rs
+++ b/clippy_lints/src/manual_range_patterns.rs
@@ -1,4 +1,5 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_opt;
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -6,6 +7,7 @@ use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{Span, DUMMY_SP};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -49,6 +51,29 @@ fn expr_as_i128(expr: &Expr<'_>) -> Option<i128> {
     }
 }
 
+#[derive(Copy, Clone)]
+struct Num {
+    val: i128,
+    span: Span,
+}
+
+impl Num {
+    fn new(expr: &Expr<'_>) -> Option<Self> {
+        Some(Self {
+            val: expr_as_i128(expr)?,
+            span: expr.span,
+        })
+    }
+
+    fn dummy(val: i128) -> Self {
+        Self { val, span: DUMMY_SP }
+    }
+
+    fn min(self, other: Self) -> Self {
+        if self.val < other.val { self } else { other }
+    }
+}
+
 impl LateLintPass<'_> for ManualRangePatterns {
     fn check_pat(&mut self, cx: &LateContext<'_>, pat: &'_ rustc_hir::Pat<'_>) {
         if in_external_macro(cx.sess(), pat.span) {
@@ -56,71 +81,83 @@ impl LateLintPass<'_> for ManualRangePatterns {
         }
 
         // a pattern like 1 | 2 seems fine, lint if there are at least 3 alternatives
+        // or at least one range
         if let PatKind::Or(pats) = pat.kind
-            && pats.len() >= 3
+            && (pats.len() >= 3 || pats.iter().any(|p| matches!(p.kind, PatKind::Range(..))))
         {
-            let mut min = i128::MAX;
-            let mut max = i128::MIN;
+            let mut min = Num::dummy(i128::MAX);
+            let mut max = Num::dummy(i128::MIN);
+            let mut range_kind = RangeEnd::Included;
             let mut numbers_found = FxHashSet::default();
             let mut ranges_found = Vec::new();
 
             for pat in pats {
                 if let PatKind::Lit(lit) = pat.kind
-                    && let Some(num) = expr_as_i128(lit)
+                    && let Some(num) = Num::new(lit)
                 {
-                    numbers_found.insert(num);
+                    numbers_found.insert(num.val);
 
                     min = min.min(num);
-                    max = max.max(num);
+                    if num.val >= max.val {
+                        max = num;
+                        range_kind = RangeEnd::Included;
+                    }
                 } else if let PatKind::Range(Some(left), Some(right), end) = pat.kind
-                    && let Some(left) = expr_as_i128(left)
-                    && let Some(right) = expr_as_i128(right)
-                    && right >= left
+                    && let Some(left) = Num::new(left)
+                    && let Some(mut right) = Num::new(right)
                 {
+                    if let RangeEnd::Excluded = end {
+                        right.val -= 1;
+                    }
+
                     min = min.min(left);
-                    max = max.max(right);
-                    ranges_found.push(left..=match end {
-                        RangeEnd::Included => right,
-                        RangeEnd::Excluded => right - 1,
-                    });
+                    if right.val > max.val {
+                        max = right;
+                        range_kind = end;
+                    }
+                    ranges_found.push(left.val..=right.val);
                 } else {
                     return;
                 }
             }
 
-            let contains_whole_range = 'contains: {
-                let mut num = min;
-                while num <= max {
-                    if numbers_found.contains(&num) {
-                        num += 1;
-                    }
-                    // Given a list of (potentially overlapping) ranges like:
-                    // 1..=5, 3..=7, 6..=10
-                    // We want to find the range with the highest end that still contains the current number
-                    else if let Some(range) = ranges_found
-                        .iter()
-                        .filter(|range| range.contains(&num))
-                        .max_by_key(|range| range.end())
-                    {
-                        num = range.end() + 1;
-                    } else {
-                        break 'contains false;
-                    }
+            let mut num = min.val;
+            while num <= max.val {
+                if numbers_found.contains(&num) {
+                    num += 1;
+                }
+                // Given a list of (potentially overlapping) ranges like:
+                // 1..=5, 3..=7, 6..=10
+                // We want to find the range with the highest end that still contains the current number
+                else if let Some(range) = ranges_found
+                    .iter()
+                    .filter(|range| range.contains(&num))
+                    .max_by_key(|range| range.end())
+                {
+                    num = range.end() + 1;
+                } else {
+                    return;
                 }
-                break 'contains true;
-            };
-
-            if contains_whole_range {
-                span_lint_and_sugg(
-                    cx,
-                    MANUAL_RANGE_PATTERNS,
-                    pat.span,
-                    "this OR pattern can be rewritten using a range",
-                    "try",
-                    format!("{min}..={max}"),
-                    Applicability::MachineApplicable,
-                );
             }
+
+            span_lint_and_then(
+                cx,
+                MANUAL_RANGE_PATTERNS,
+                pat.span,
+                "this OR pattern can be rewritten using a range",
+                |diag| {
+                    if let Some(min) = snippet_opt(cx, min.span)
+                        && let Some(max) = snippet_opt(cx, max.span)
+                    {
+                        diag.span_suggestion(
+                            pat.span,
+                            "try",
+                            format!("{min}{range_kind}{max}"),
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                },
+            );
         }
     }
 }
diff --git a/clippy_lints/src/methods/iter_out_of_bounds.rs b/clippy_lints/src/methods/iter_out_of_bounds.rs
new file mode 100644
index 00000000000..79c6d63254b
--- /dev/null
+++ b/clippy_lints/src/methods/iter_out_of_bounds.rs
@@ -0,0 +1,106 @@
+use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::higher::VecArgs;
+use clippy_utils::{expr_or_init, is_trait_method, match_def_path, paths};
+use rustc_ast::LitKind;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self};
+use rustc_span::sym;
+
+use super::ITER_OUT_OF_BOUNDS;
+
+fn expr_as_u128(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<u128> {
+    if let ExprKind::Lit(lit) = expr_or_init(cx, e).kind
+        && let LitKind::Int(n, _) = lit.node
+    {
+        Some(n)
+    } else {
+        None
+    }
+}
+
+/// Attempts to extract the length out of an iterator expression.
+fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) -> Option<u128> {
+    let ty::Adt(adt, substs) = cx.typeck_results().expr_ty(iter).kind() else {
+        return None;
+    };
+    let did = adt.did();
+
+    if match_def_path(cx, did, &paths::ARRAY_INTO_ITER) {
+        // For array::IntoIter<T, const N: usize>, the length is the second generic
+        // parameter.
+        substs
+            .const_at(1)
+            .try_eval_target_usize(cx.tcx, cx.param_env)
+            .map(u128::from)
+    } else if match_def_path(cx, did, &paths::SLICE_ITER)
+        && let ExprKind::MethodCall(_, recv, ..) = iter.kind
+    {
+        if let ty::Array(_, len) = cx.typeck_results().expr_ty(recv).peel_refs().kind() {
+            // For slice::Iter<'_, T>, the receiver might be an array literal: [1,2,3].iter().skip(..)
+            len.try_eval_target_usize(cx.tcx, cx.param_env).map(u128::from)
+        } else if let Some(args) = VecArgs::hir(cx, expr_or_init(cx, recv)) {
+            match args {
+                VecArgs::Vec(vec) => vec.len().try_into().ok(),
+                VecArgs::Repeat(_, len) => expr_as_u128(cx, len),
+            }
+        } else {
+            None
+        }
+    } else if match_def_path(cx, did, &paths::ITER_EMPTY) {
+        Some(0)
+    } else if match_def_path(cx, did, &paths::ITER_ONCE) {
+        Some(1)
+    }  else {
+        None
+    }
+}
+
+fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    recv: &'tcx Expr<'tcx>,
+    arg: &'tcx Expr<'tcx>,
+    message: &'static str,
+    note: &'static str,
+) {
+    if is_trait_method(cx, expr, sym::Iterator)
+        && let Some(len) = get_iterator_length(cx, recv)
+        && let Some(skipped) = expr_as_u128(cx, arg)
+        && skipped > len
+    {
+        span_lint_and_note(cx, ITER_OUT_OF_BOUNDS, expr.span, message, None, note);
+    }
+}
+
+pub(super) fn check_skip<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    recv: &'tcx Expr<'tcx>,
+    arg: &'tcx Expr<'tcx>,
+) {
+    check(
+        cx,
+        expr,
+        recv,
+        arg,
+        "this `.skip()` call skips more items than the iterator will produce",
+        "this operation is useless and will create an empty iterator",
+    );
+}
+
+pub(super) fn check_take<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    recv: &'tcx Expr<'tcx>,
+    arg: &'tcx Expr<'tcx>,
+) {
+    check(
+        cx,
+        expr,
+        recv,
+        arg,
+        "this `.take()` call takes more items than the iterator will produce",
+        "this operation is useless and the returned iterator will simply yield the same items",
+    );
+}
diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs
index ee405a3e30c..a49dd98db87 100644
--- a/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -21,7 +21,7 @@ pub(super) enum Op<'a> {
     RmCloned,
 
     // rm `.cloned()`
-    // e.g. `map` `for_each`
+    // e.g. `map` `for_each` `all` `any`
     NeedlessMove(&'a str, &'a Expr<'a>),
 
     // later `.cloned()`
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 5075137caa0..81223fa8d95 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -43,6 +43,7 @@ mod iter_next_slice;
 mod iter_nth;
 mod iter_nth_zero;
 mod iter_on_single_or_empty_collections;
+mod iter_out_of_bounds;
 mod iter_overeager_cloned;
 mod iter_skip_next;
 mod iter_skip_zero;
@@ -3054,12 +3055,12 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// ```rust
-    /// vec!(1, 2, 3, 4, 5).resize(0, 5)
+    /// vec![1, 2, 3, 4, 5].resize(0, 5)
     /// ```
     ///
     /// Use instead:
     /// ```rust
-    /// vec!(1, 2, 3, 4, 5).clear()
+    /// vec![1, 2, 3, 4, 5].clear()
     /// ```
     #[clippy::version = "1.46.0"]
     pub VEC_RESIZE_TO_ZERO,
@@ -3538,6 +3539,30 @@ declare_clippy_lint! {
     "acquiring a write lock when a read lock would work"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Looks for iterator combinator calls such as `.take(x)` or `.skip(x)`
+    /// where `x` is greater than the amount of items that an iterator will produce.
+    ///
+    /// ### Why is this bad?
+    /// Taking or skipping more items than there are in an iterator either creates an iterator
+    /// with all items from the original iterator or an iterator with no items at all.
+    /// This is most likely not what the user intended to do.
+    ///
+    /// ### Example
+    /// ```rust
+    /// for _ in [1, 2, 3].iter().take(4) {}
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// for _ in [1, 2, 3].iter() {}
+    /// ```
+    #[clippy::version = "1.74.0"]
+    pub ITER_OUT_OF_BOUNDS,
+    suspicious,
+    "calls to `.take()` or `.skip()` that are out of bounds"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3676,7 +3701,8 @@ impl_lint_pass!(Methods => [
     STRING_LIT_CHARS_ANY,
     ITER_SKIP_ZERO,
     FILTER_MAP_BOOL_THEN,
-    READONLY_WRITE_LOCK
+    READONLY_WRITE_LOCK,
+    ITER_OUT_OF_BOUNDS,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -3873,6 +3899,12 @@ impl Methods {
                 ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => {
                     zst_offset::check(cx, expr, recv);
                 },
+                ("all", [arg]) => {
+                    if let Some(("cloned", recv2, [], _, _)) = method_call(recv) {
+                        iter_overeager_cloned::check(cx, expr, recv, recv2,
+                                iter_overeager_cloned::Op::NeedlessMove(name, arg), false);
+                    }
+                }
                 ("and_then", [arg]) => {
                     let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg);
                     let biom_result_linted = bind_instead_of_map::ResultAndThenOk::check(cx, expr, recv, arg);
@@ -3880,12 +3912,16 @@ impl Methods {
                         unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
                     }
                 },
-                ("any", [arg]) if let ExprKind::Closure(arg) = arg.kind
-                    && let body = cx.tcx.hir().body(arg.body)
-                    && let [param] = body.params
-                    && let Some(("chars", recv, _, _, _)) = method_call(recv) =>
-                {
-                    string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
+                ("any", [arg]) => {
+                    match method_call(recv) {
+                        Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::NeedlessMove(name, arg), false),
+                        Some(("chars", recv, _, _, _)) if let ExprKind::Closure(arg) = arg.kind
+                        && let body = cx.tcx.hir().body(arg.body)
+                        && let [param] = body.params => {
+                            string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
+                        }
+                        _ => {}
+                    }
                 }
                 ("arg", [arg]) => {
                     suspicious_command_arg_space::check(cx, recv, arg, span);
@@ -4136,6 +4172,7 @@ impl Methods {
                 },
                 ("skip", [arg]) => {
                     iter_skip_zero::check(cx, expr, arg);
+                    iter_out_of_bounds::check_skip(cx, expr, recv, arg);
 
                     if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
                         iter_overeager_cloned::check(cx, expr, recv, recv2,
@@ -4163,7 +4200,8 @@ impl Methods {
                     }
                 },
                 ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
-                ("take", [_arg]) => {
+                ("take", [arg]) => {
+                    iter_out_of_bounds::check_take(cx, expr, recv, arg);
                     if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
                         iter_overeager_cloned::check(cx, expr, recv, recv2,
                                 iter_overeager_cloned::Op::LaterCloned, false);
diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs
new file mode 100644
index 00000000000..08fec2b8ec8
--- /dev/null
+++ b/clippy_lints/src/missing_asserts_for_indexing.rs
@@ -0,0 +1,391 @@
+use std::mem;
+use std::ops::ControlFlow;
+
+use clippy_utils::comparisons::{normalize_comparison, Rel};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use clippy_utils::visitors::for_each_expr;
+use clippy_utils::{eq_expr_value, hash_expr, higher};
+use rustc_ast::{LitKind, RangeLimits};
+use rustc_data_structures::unhash::UnhashMap;
+use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir::{BinOp, Block, Expr, ExprKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::source_map::Spanned;
+use rustc_span::{sym, Span};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for repeated slice indexing without asserting beforehand that the length
+    /// is greater than the largest index used to index into the slice.
+    ///
+    /// ### Why is this bad?
+    /// In the general case where the compiler does not have a lot of information
+    /// about the length of a slice, indexing it repeatedly will generate a bounds check
+    /// for every single index.
+    ///
+    /// Asserting that the length of the slice is at least as large as the largest value
+    /// to index beforehand gives the compiler enough information to elide the bounds checks,
+    /// effectively reducing the number of bounds checks from however many times
+    /// the slice was indexed to just one (the assert).
+    ///
+    /// ### Drawbacks
+    /// False positives. It is, in general, very difficult to predict how well
+    /// the optimizer will be able to elide bounds checks and it very much depends on
+    /// the surrounding code. For example, indexing into the slice yielded by the
+    /// [`slice::chunks_exact`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.chunks_exact)
+    /// iterator will likely have all of the bounds checks elided even without an assert
+    /// if the `chunk_size` is a constant.
+    ///
+    /// Asserts are not tracked across function calls. Asserting the length of a slice
+    /// in a different function likely gives the optimizer enough information
+    /// about the length of a slice, but this lint will not detect that.
+    ///
+    /// ### Example
+    /// ```rust
+    /// fn sum(v: &[u8]) -> u8 {
+    ///     // 4 bounds checks
+    ///     v[0] + v[1] + v[2] + v[3]
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// fn sum(v: &[u8]) -> u8 {
+    ///     assert!(v.len() > 4);
+    ///     // no bounds checks
+    ///     v[0] + v[1] + v[2] + v[3]
+    /// }
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub MISSING_ASSERTS_FOR_INDEXING,
+    restriction,
+    "indexing into a slice multiple times without an `assert`"
+}
+declare_lint_pass!(MissingAssertsForIndexing => [MISSING_ASSERTS_FOR_INDEXING]);
+
+fn report_lint<F>(cx: &LateContext<'_>, full_span: Span, msg: &str, indexes: &[Span], f: F)
+where
+    F: FnOnce(&mut Diagnostic),
+{
+    span_lint_and_then(cx, MISSING_ASSERTS_FOR_INDEXING, full_span, msg, |diag| {
+        f(diag);
+        for span in indexes {
+            diag.span_note(*span, "slice indexed here");
+        }
+        diag.note("asserting the length before indexing will elide bounds checks");
+    });
+}
+
+#[derive(Copy, Clone, Debug)]
+enum LengthComparison {
+    /// `v.len() < 5`
+    LengthLessThanInt,
+    /// `5 < v.len()`
+    IntLessThanLength,
+    /// `v.len() <= 5`
+    LengthLessThanOrEqualInt,
+    /// `5 <= v.len()`
+    IntLessThanOrEqualLength,
+}
+
+/// Extracts parts out of a length comparison expression.
+///
+/// E.g. for `v.len() > 5` this returns `Some((LengthComparison::IntLessThanLength, 5, `v.len()`))`
+fn len_comparison<'hir>(
+    bin_op: BinOp,
+    left: &'hir Expr<'hir>,
+    right: &'hir Expr<'hir>,
+) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> {
+    macro_rules! int_lit_pat {
+        ($id:ident) => {
+            ExprKind::Lit(Spanned {
+                node: LitKind::Int($id, _),
+                ..
+            })
+        };
+    }
+
+    // normalize comparison, `v.len() > 4` becomes `4 < v.len()`
+    // this simplifies the logic a bit
+    let (op, left, right) = normalize_comparison(bin_op.node, left, right)?;
+    match (op, &left.kind, &right.kind) {
+        (Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, *left as usize, right)),
+        (Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, *right as usize, left)),
+        (Rel::Le, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanOrEqualLength, *left as usize, right)),
+        (Rel::Le, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanOrEqualInt, *right as usize, left)),
+        _ => None,
+    }
+}
+
+/// Attempts to extract parts out of an `assert!`-like expression
+/// in the form `assert!(some_slice.len() > 5)`.
+///
+/// `assert!` has expanded to an if expression at the HIR, so this
+/// actually works not just with `assert!` specifically, but anything
+/// that has a never type expression in the `then` block (e.g. `panic!`).
+fn assert_len_expr<'hir>(
+    cx: &LateContext<'_>,
+    expr: &'hir Expr<'hir>,
+) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> {
+    if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr)
+        && let ExprKind::Unary(UnOp::Not, condition) = &cond.kind
+        && let ExprKind::Binary(bin_op, left, right) = &condition.kind
+
+        && let Some((cmp, asserted_len, slice_len)) = len_comparison(*bin_op, left, right)
+        && let ExprKind::MethodCall(method, recv, ..) = &slice_len.kind
+        && cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice()
+        && method.ident.name == sym::len
+
+        // check if `then` block has a never type expression
+        && let ExprKind::Block(Block { expr: Some(then_expr), .. }, _) = then.kind
+        && cx.typeck_results().expr_ty(then_expr).is_never()
+    {
+        Some((cmp, asserted_len, recv))
+    } else {
+        None
+    }
+}
+
+#[derive(Debug)]
+enum IndexEntry<'hir> {
+    /// `assert!` without any indexing (so far)
+    StrayAssert {
+        asserted_len: usize,
+        comparison: LengthComparison,
+        assert_span: Span,
+        slice: &'hir Expr<'hir>,
+    },
+    /// `assert!` with indexing
+    ///
+    /// We also store the highest index to be able to check
+    /// if the `assert!` asserts the right length.
+    AssertWithIndex {
+        highest_index: usize,
+        asserted_len: usize,
+        assert_span: Span,
+        slice: &'hir Expr<'hir>,
+        indexes: Vec<Span>,
+        comparison: LengthComparison,
+    },
+    /// Indexing without an `assert!`
+    IndexWithoutAssert {
+        highest_index: usize,
+        indexes: Vec<Span>,
+        slice: &'hir Expr<'hir>,
+    },
+}
+
+impl<'hir> IndexEntry<'hir> {
+    pub fn slice(&self) -> &'hir Expr<'hir> {
+        match self {
+            IndexEntry::StrayAssert { slice, .. }
+            | IndexEntry::AssertWithIndex { slice, .. }
+            | IndexEntry::IndexWithoutAssert { slice, .. } => slice,
+        }
+    }
+
+    pub fn index_spans(&self) -> Option<&[Span]> {
+        match self {
+            IndexEntry::StrayAssert { .. } => None,
+            IndexEntry::AssertWithIndex { indexes, .. } | IndexEntry::IndexWithoutAssert { indexes, .. } => {
+                Some(indexes)
+            },
+        }
+    }
+}
+
+/// Extracts the upper index of a slice indexing expression.
+///
+/// E.g. for `5` this returns `Some(5)`, for `..5` this returns `Some(4)`,
+/// for `..=5` this returns `Some(5)`
+fn upper_index_expr(expr: &Expr<'_>) -> Option<usize> {
+    if let ExprKind::Lit(lit) = &expr.kind && let LitKind::Int(index, _) = lit.node {
+        Some(index as usize)
+    } else if let Some(higher::Range { end: Some(end), limits, .. }) = higher::Range::hir(expr)
+        && let ExprKind::Lit(lit) = &end.kind
+        && let LitKind::Int(index @ 1.., _) = lit.node
+    {
+        match limits {
+            RangeLimits::HalfOpen => Some(index as usize - 1),
+            RangeLimits::Closed => Some(index as usize),
+        }
+    } else {
+        None
+    }
+}
+
+/// Checks if the expression is an index into a slice and adds it to `indexes`
+fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnhashMap<u64, Vec<IndexEntry<'hir>>>) {
+    if let ExprKind::Index(slice, index_lit, _) = expr.kind
+        && cx.typeck_results().expr_ty_adjusted(slice).peel_refs().is_slice()
+        && let Some(index) = upper_index_expr(index_lit)
+    {
+        let hash = hash_expr(cx, slice);
+
+        let indexes = map.entry(hash).or_default();
+        let entry = indexes.iter_mut().find(|entry| eq_expr_value(cx, entry.slice(), slice));
+
+        if let Some(entry) = entry {
+            match entry {
+                IndexEntry::StrayAssert { asserted_len, comparison, assert_span, slice } => {
+                    *entry = IndexEntry::AssertWithIndex {
+                        highest_index: index,
+                        asserted_len: *asserted_len,
+                        assert_span: *assert_span,
+                        slice,
+                        indexes: vec![expr.span],
+                        comparison: *comparison,
+                    };
+                },
+                IndexEntry::IndexWithoutAssert { highest_index, indexes, .. }
+                | IndexEntry::AssertWithIndex { highest_index, indexes, .. } => {
+                    indexes.push(expr.span);
+                    *highest_index = (*highest_index).max(index);
+                },
+            }
+        } else {
+            indexes.push(IndexEntry::IndexWithoutAssert {
+                highest_index: index,
+                indexes: vec![expr.span],
+                slice,
+            });
+        }
+    }
+}
+
+/// Checks if the expression is an `assert!` expression and adds it to `asserts`
+fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnhashMap<u64, Vec<IndexEntry<'hir>>>) {
+    if let Some((comparison, asserted_len, slice)) = assert_len_expr(cx, expr) {
+        let hash = hash_expr(cx, slice);
+        let indexes = map.entry(hash).or_default();
+
+        let entry = indexes.iter_mut().find(|entry| eq_expr_value(cx, entry.slice(), slice));
+
+        if let Some(entry) = entry {
+            if let IndexEntry::IndexWithoutAssert {
+                highest_index,
+                indexes,
+                slice,
+            } = entry
+            {
+                *entry = IndexEntry::AssertWithIndex {
+                    highest_index: *highest_index,
+                    indexes: mem::take(indexes),
+                    slice,
+                    assert_span: expr.span,
+                    comparison,
+                    asserted_len,
+                };
+            }
+        } else {
+            indexes.push(IndexEntry::StrayAssert {
+                asserted_len,
+                comparison,
+                assert_span: expr.span,
+                slice,
+            });
+        }
+    }
+}
+
+/// Inspects indexes and reports lints.
+///
+/// Called at the end of this lint after all indexing and `assert!` expressions have been collected.
+fn report_indexes(cx: &LateContext<'_>, map: &UnhashMap<u64, Vec<IndexEntry<'_>>>) {
+    for bucket in map.values() {
+        for entry in bucket {
+            let Some(full_span) = entry
+                .index_spans()
+                .and_then(|spans| spans.first().zip(spans.last()))
+                .map(|(low, &high)| low.to(high))
+            else {
+                continue;
+            };
+
+            match entry {
+                IndexEntry::AssertWithIndex {
+                    highest_index,
+                    asserted_len,
+                    indexes,
+                    comparison,
+                    assert_span,
+                    slice,
+                } if indexes.len() > 1 => {
+                    // if we have found an `assert!`, let's also check that it's actually right
+                    // and if it convers the highest index and if not, suggest the correct length
+                    let sugg = match comparison {
+                        // `v.len() < 5` and `v.len() <= 5` does nothing in terms of bounds checks.
+                        // The user probably meant `v.len() > 5`
+                        LengthComparison::LengthLessThanInt | LengthComparison::LengthLessThanOrEqualInt => Some(
+                            format!("assert!({}.len() > {highest_index})", snippet(cx, slice.span, "..")),
+                        ),
+                        // `5 < v.len()` == `v.len() > 5`
+                        LengthComparison::IntLessThanLength if asserted_len < highest_index => Some(format!(
+                            "assert!({}.len() > {highest_index})",
+                            snippet(cx, slice.span, "..")
+                        )),
+                        // `5 <= v.len() == `v.len() >= 5`
+                        LengthComparison::IntLessThanOrEqualLength if asserted_len <= highest_index => Some(format!(
+                            "assert!({}.len() > {highest_index})",
+                            snippet(cx, slice.span, "..")
+                        )),
+                        _ => None,
+                    };
+
+                    if let Some(sugg) = sugg {
+                        report_lint(
+                            cx,
+                            full_span,
+                            "indexing into a slice multiple times with an `assert` that does not cover the highest index",
+                            indexes,
+                            |diag| {
+                                diag.span_suggestion(
+                                    *assert_span,
+                                    "provide the highest index that is indexed with",
+                                    sugg,
+                                    Applicability::MachineApplicable,
+                                );
+                            },
+                        );
+                    }
+                },
+                IndexEntry::IndexWithoutAssert {
+                    indexes,
+                    highest_index,
+                    slice,
+                } if indexes.len() > 1 => {
+                    // if there was no `assert!` but more than one index, suggest
+                    // adding an `assert!` that covers the highest index
+                    report_lint(
+                        cx,
+                        full_span,
+                        "indexing into a slice multiple times without an `assert`",
+                        indexes,
+                        |diag| {
+                            diag.help(format!(
+                                "consider asserting the length before indexing: `assert!({}.len() > {highest_index});`",
+                                snippet(cx, slice.span, "..")
+                            ));
+                        },
+                    );
+                },
+                _ => {},
+            }
+        }
+    }
+}
+
+impl LateLintPass<'_> for MissingAssertsForIndexing {
+    fn check_block(&mut self, cx: &LateContext<'_>, block: &Block<'_>) {
+        let mut map = UnhashMap::default();
+
+        for_each_expr(block, |expr| {
+            check_index(cx, expr, &mut map);
+            check_assert(cx, expr, &mut map);
+            ControlFlow::<!, ()>::Continue(())
+        });
+
+        report_indexes(cx, &map);
+    }
+}
diff --git a/clippy_lints/src/incorrect_impls.rs b/clippy_lints/src/non_canonical_impls.rs
similarity index 88%
rename from clippy_lints/src/incorrect_impls.rs
rename to clippy_lints/src/non_canonical_impls.rs
index 3c59b839a39..4b24f059afd 100644
--- a/clippy_lints/src/incorrect_impls.rs
+++ b/clippy_lints/src/non_canonical_impls.rs
@@ -13,11 +13,12 @@ use rustc_span::symbol::kw;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for manual implementations of `Clone` when `Copy` is already implemented.
+    /// Checks for non-canonical implementations of `Clone` when `Copy` is already implemented.
     ///
     /// ### Why is this bad?
-    /// If both `Clone` and `Copy` are implemented, they must agree. This is done by dereferencing
-    /// `self` in `Clone`'s implementation. Anything else is incorrect.
+    /// If both `Clone` and `Copy` are implemented, they must agree. This can done by dereferencing
+    /// `self` in `Clone`'s implementation, which will avoid any possibility of the implementations
+    /// becoming out of sync.
     ///
     /// ### Example
     /// ```rust,ignore
@@ -46,14 +47,13 @@ declare_clippy_lint! {
     /// impl Copy for A {}
     /// ```
     #[clippy::version = "1.72.0"]
-    pub INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
-    correctness,
-    "manual implementation of `Clone` on a `Copy` type"
+    pub NON_CANONICAL_CLONE_IMPL,
+    suspicious,
+    "non-canonical implementation of `Clone` on a `Copy` type"
 }
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for manual implementations of both `PartialOrd` and `Ord` when only `Ord` is
-    /// necessary.
+    /// Checks for non-canonical implementations of `PartialOrd` when `Ord` is already implemented.
     ///
     /// ### Why is this bad?
     /// If both `PartialOrd` and `Ord` are implemented, they must agree. This is commonly done by
@@ -61,11 +61,8 @@ declare_clippy_lint! {
     /// introduce an error upon refactoring.
     ///
     /// ### Known issues
-    /// Code that calls the `.into()` method instead will be flagged as incorrect, despite `.into()`
-    /// wrapping it in `Some`.
-    ///
-    /// ### Limitations
-    /// Will not lint if `Self` and `Rhs` do not have the same type.
+    /// Code that calls the `.into()` method instead will be flagged, despite `.into()` wrapping it
+    /// in `Some`.
     ///
     /// ### Example
     /// ```rust
@@ -107,13 +104,13 @@ declare_clippy_lint! {
     /// }
     /// ```
     #[clippy::version = "1.72.0"]
-    pub INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE,
-    correctness,
-    "manual implementation of `PartialOrd` when `Ord` is already implemented"
+    pub NON_CANONICAL_PARTIAL_ORD_IMPL,
+    suspicious,
+    "non-canonical implementation of `PartialOrd` on an `Ord` type"
 }
-declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE, INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE]);
+declare_lint_pass!(NonCanonicalImpls => [NON_CANONICAL_CLONE_IMPL, NON_CANONICAL_PARTIAL_ORD_IMPL]);
 
-impl LateLintPass<'_> for IncorrectImpls {
+impl LateLintPass<'_> for NonCanonicalImpls {
     #[expect(clippy::too_many_lines)]
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
         let Some(Node::Item(item)) = get_parent_node(cx.tcx, impl_item.hir_id()) else {
@@ -154,9 +151,9 @@ impl LateLintPass<'_> for IncorrectImpls {
                 {} else {
                     span_lint_and_sugg(
                         cx,
-                        INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
+                        NON_CANONICAL_CLONE_IMPL,
                         block.span,
-                        "incorrect implementation of `clone` on a `Copy` type",
+                        "non-canonical implementation of `clone` on a `Copy` type",
                         "change this to",
                         "{ *self }".to_owned(),
                         Applicability::MaybeIncorrect,
@@ -169,9 +166,9 @@ impl LateLintPass<'_> for IncorrectImpls {
             if impl_item.ident.name == sym::clone_from {
                 span_lint_and_sugg(
                     cx,
-                    INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
+                    NON_CANONICAL_CLONE_IMPL,
                     impl_item.span,
-                    "incorrect implementation of `clone_from` on a `Copy` type",
+                    "unnecessary implementation of `clone_from` on a `Copy` type",
                     "remove it",
                     String::new(),
                     Applicability::MaybeIncorrect,
@@ -222,9 +219,9 @@ impl LateLintPass<'_> for IncorrectImpls {
 
                 span_lint_and_then(
                     cx,
-                    INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE,
+                    NON_CANONICAL_PARTIAL_ORD_IMPL,
                     item.span,
-                    "incorrect implementation of `partial_cmp` on an `Ord` type",
+                    "non-canonical implementation of `partial_cmp` on an `Ord` type",
                     |diag| {
                         let [_, other] = body.params else {
                             return;
diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs
index a687c7d29b5..8072aded851 100644
--- a/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -14,7 +14,12 @@ use {rustc_ast as ast, rustc_hir as hir};
 
 const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[["f32", "f32"], ["f64", "f64"], ["std::string::String", "str"]];
 const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
-const INTEGER_METHODS: &[Symbol] = &[sym::saturating_div, sym::wrapping_div, sym::wrapping_rem, sym::wrapping_rem_euclid];
+const INTEGER_METHODS: &[Symbol] = &[
+    sym::saturating_div,
+    sym::wrapping_div,
+    sym::wrapping_rem,
+    sym::wrapping_rem_euclid,
+];
 
 #[derive(Debug)]
 pub struct ArithmeticSideEffects {
@@ -93,7 +98,14 @@ impl ArithmeticSideEffects {
         let is_non_zero_u = |symbol: Option<Symbol>| {
             matches!(
                 symbol,
-                Some(sym::NonZeroU128 | sym::NonZeroU16 | sym::NonZeroU32 | sym::NonZeroU64 | sym::NonZeroU8 | sym::NonZeroUsize)
+                Some(
+                    sym::NonZeroU128
+                        | sym::NonZeroU16
+                        | sym::NonZeroU32
+                        | sym::NonZeroU64
+                        | sym::NonZeroU8
+                        | sym::NonZeroUsize
+                )
             )
         };
         let is_sat_or_wrap = |ty: Ty<'_>| {
diff --git a/clippy_lints/src/operators/float_cmp.rs b/clippy_lints/src/operators/float_cmp.rs
index f3e0c58a787..bce6bdcaf61 100644
--- a/clippy_lints/src/operators/float_cmp.rs
+++ b/clippy_lints/src/operators/float_cmp.rs
@@ -17,7 +17,7 @@ pub(crate) fn check<'tcx>(
     left: &'tcx Expr<'_>,
     right: &'tcx Expr<'_>,
 ) {
-    if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
+    if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) {
         let left_is_local = match constant_with_source(cx, cx.typeck_results(), left) {
             Some((c, s)) if !is_allowed(&c) => s.is_local(),
             Some(_) => return,
diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs
index ccabb577cb7..e8018462d75 100644
--- a/clippy_lints/src/raw_strings.rs
+++ b/clippy_lints/src/raw_strings.rs
@@ -1,7 +1,7 @@
 use std::iter::once;
 use std::ops::ControlFlow;
 
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_ast::token::LitKind;
@@ -9,6 +9,7 @@ use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{BytePos, Pos, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -76,14 +77,33 @@ impl EarlyLintPass for RawStrings {
             }
 
             if !str.contains(['\\', '"']) {
-                span_lint_and_sugg(
+                span_lint_and_then(
                     cx,
                     NEEDLESS_RAW_STRINGS,
                     expr.span,
                     "unnecessary raw string literal",
-                    "try",
-                    format!("{}\"{}\"", prefix.replace('r', ""), lit.symbol),
-                    Applicability::MachineApplicable,
+                    |diag| {
+                        let (start, end) = hash_spans(expr.span, prefix, 0, max);
+
+                        // BytePos: skip over the `b` in `br`, we checked the prefix appears in the source text
+                        let r_pos = expr.span.lo() + BytePos::from_usize(prefix.len() - 1);
+                        let start = start.with_lo(r_pos);
+
+                        if end.is_empty() {
+                            diag.span_suggestion(
+                                start,
+                                "use a string literal instead",
+                                format!("\"{}\"", str),
+                                Applicability::MachineApplicable,
+                            );
+                        } else {
+                            diag.multipart_suggestion(
+                                "try",
+                                vec![(start, String::new()), (end, String::new())],
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    },
                 );
 
                 return;
@@ -96,13 +116,6 @@ impl EarlyLintPass for RawStrings {
                 let num = str.as_bytes().iter().chain(once(&0)).try_fold(0u8, |acc, &b| {
                     match b {
                         b'"' if !following_quote => (following_quote, req) = (true, 1),
-                        // I'm a bit surprised the compiler didn't optimize this out, there's no
-                        // branch but it still ends up doing an unnecessary comparison, it's:
-                        // - cmp r9b,1h
-                        // - sbb cl,-1h
-                        // which will add 1 if it's true. With this change, it becomes:
-                        // - add cl,r9b
-                        // isn't that so much nicer?
                         b'#' => req += u8::from(following_quote),
                         _ => {
                             if following_quote {
@@ -126,18 +139,58 @@ impl EarlyLintPass for RawStrings {
             };
 
             if req < max {
-                let hashes = "#".repeat(req as usize);
-
-                span_lint_and_sugg(
+                span_lint_and_then(
                     cx,
                     NEEDLESS_RAW_STRING_HASHES,
                     expr.span,
                     "unnecessary hashes around raw string literal",
-                    "try",
-                    format!(r#"{prefix}{hashes}"{}"{hashes}"#, lit.symbol),
-                    Applicability::MachineApplicable,
+                    |diag| {
+                        let (start, end) = hash_spans(expr.span, prefix, req, max);
+
+                        let message = match max - req {
+                            _ if req == 0 => "remove all the hashes around the literal".to_string(),
+                            1 => "remove one hash from both sides of the literal".to_string(),
+                            n => format!("remove {n} hashes from both sides of the literal"),
+                        };
+
+                        diag.multipart_suggestion(
+                            message,
+                            vec![(start, String::new()), (end, String::new())],
+                            Applicability::MachineApplicable,
+                        );
+                    },
                 );
             }
         }
     }
 }
+
+/// Returns spans pointing at the unneeded hashes, e.g. for a `req` of `1` and `max` of `3`:
+///
+/// ```ignore
+/// r###".."###
+///   ^^    ^^
+/// ```
+fn hash_spans(literal_span: Span, prefix: &str, req: u8, max: u8) -> (Span, Span) {
+    let literal_span = literal_span.data();
+
+    // BytePos: we checked prefix appears literally in the source text
+    let hash_start = literal_span.lo + BytePos::from_usize(prefix.len());
+    let hash_end = literal_span.hi;
+
+    // BytePos: req/max are counts of the ASCII character #
+    let start = Span::new(
+        hash_start + BytePos(req.into()),
+        hash_start + BytePos(max.into()),
+        literal_span.ctxt,
+        None,
+    );
+    let end = Span::new(
+        hash_end - BytePos(req.into()),
+        hash_end - BytePos(max.into()),
+        literal_span.ctxt,
+        None,
+    );
+
+    (start, end)
+}
diff --git a/clippy_lints/src/renamed_lints.rs b/clippy_lints/src/renamed_lints.rs
index fc1fabcc0ae..613f1ecc6fb 100644
--- a/clippy_lints/src/renamed_lints.rs
+++ b/clippy_lints/src/renamed_lints.rs
@@ -15,6 +15,8 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
     ("clippy::identity_conversion", "clippy::useless_conversion"),
     ("clippy::if_let_some_result", "clippy::match_result_ok"),
+    ("clippy::incorrect_clone_impl_on_copy_type", "clippy::non_canonical_clone_impl"),
+    ("clippy::incorrect_partial_ord_impl_on_ord_type", "clippy::non_canonical_partial_ord_impl"),
     ("clippy::integer_arithmetic", "clippy::arithmetic_side_effects"),
     ("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
     ("clippy::new_without_default_derive", "clippy::new_without_default"),
@@ -38,12 +40,12 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::drop_bounds", "drop_bounds"),
     ("clippy::drop_copy", "dropping_copy_types"),
     ("clippy::drop_ref", "dropping_references"),
+    ("clippy::fn_null_check", "useless_ptr_null_checks"),
     ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
     ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
     ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
     ("clippy::forget_copy", "forgetting_copy_types"),
     ("clippy::forget_ref", "forgetting_references"),
-    ("clippy::fn_null_check", "useless_ptr_null_checks"),
     ("clippy::into_iter_on_array", "array_into_iter"),
     ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
     ("clippy::invalid_ref", "invalid_value"),
diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index c9ab622ad25..9db18c2976c 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::macros::root_macro_call;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
     get_enclosing_block, is_expr_path_def_path, is_integer_literal, is_path_diagnostic_item, path_to_local,
@@ -148,6 +149,15 @@ impl SlowVectorInit {
     /// - `Some(InitializedSize::Uninitialized)` for `Vec::new()`
     /// - `None` for other, unrelated kinds of expressions
     fn as_vec_initializer<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<InitializedSize<'tcx>> {
+        // Generally don't warn if the vec initializer comes from an expansion, except for the vec! macro.
+        // This lets us still warn on `vec![]`, while ignoring other kinds of macros that may output an
+        // empty vec
+        if expr.span.from_expansion()
+            && root_macro_call(expr.span).map(|m| m.def_id) != cx.tcx.get_diagnostic_item(sym::vec_macro)
+        {
+            return None;
+        }
+
         if let ExprKind::Call(func, [len_expr]) = expr.kind
             && is_expr_path_def_path(cx, func, &paths::VEC_WITH_CAPACITY)
         {
@@ -205,7 +215,7 @@ impl SlowVectorInit {
 
         span_lint_and_then(cx, SLOW_VECTOR_INITIALIZATION, slow_fill.span, msg, |diag| {
             diag.span_suggestion(
-                vec_alloc.allocation_expr.span,
+                vec_alloc.allocation_expr.span.source_callsite(),
                 "consider replacing this with",
                 format!("vec![0; {len_expr}]"),
                 Applicability::Unspecified,
diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs
index f239165276f..5f54a10d1c4 100644
--- a/clippy_lints/src/std_instead_of_core.rs
+++ b/clippy_lints/src/std_instead_of_core.rs
@@ -1,4 +1,5 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{HirId, Path, PathSegment};
@@ -99,17 +100,17 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
             && let Some(first_segment) = get_first_segment(path)
             && is_stable(cx, def_id)
         {
-            let (lint, msg, help) = match first_segment.ident.name {
+            let (lint, used_mod, replace_with) = match first_segment.ident.name {
                 sym::std => match cx.tcx.crate_name(def_id.krate) {
                     sym::core => (
                         STD_INSTEAD_OF_CORE,
-                        "used import from `std` instead of `core`",
-                        "consider importing the item from `core`",
+                        "std",
+                        "core",
                     ),
                     sym::alloc => (
                         STD_INSTEAD_OF_ALLOC,
-                        "used import from `std` instead of `alloc`",
-                        "consider importing the item from `alloc`",
+                        "std",
+                        "alloc",
                     ),
                     _ => {
                         self.prev_span = path.span;
@@ -120,8 +121,8 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                     if cx.tcx.crate_name(def_id.krate) == sym::core {
                         (
                             ALLOC_INSTEAD_OF_CORE,
-                            "used import from `alloc` instead of `core`",
-                            "consider importing the item from `core`",
+                            "alloc",
+                            "core",
                         )
                     } else {
                         self.prev_span = path.span;
@@ -131,7 +132,14 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                 _ => return,
             };
             if path.span != self.prev_span {
-                span_lint_and_help(cx, lint, path.span, msg, None, help);
+                span_lint_and_sugg(
+                    cx,
+                    lint,
+                    first_segment.ident.span,
+                    &format!("used import from `{used_mod}` instead of `{replace_with}`"),
+                    &format!("consider importing the item from `{replace_with}`"),
+                    replace_with.to_string(),
+                    Applicability::MachineApplicable);
                 self.prev_span = path.span;
             }
         }
diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs
index da8d8ed4c0f..6193fdeb433 100644
--- a/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -341,44 +341,21 @@ fn block_parents_have_safety_comment(
     id: hir::HirId,
 ) -> bool {
     if let Some(node) = get_parent_node(cx.tcx, id) {
-        return match node {
-            Node::Expr(expr) => {
-                if let Some(
-                    Node::Local(hir::Local { span, .. })
-                    | Node::Item(hir::Item {
-                        kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
-                        span,
-                        ..
-                    }),
-                ) = get_parent_node(cx.tcx, expr.hir_id)
-                {
-                    let hir_id = match get_parent_node(cx.tcx, expr.hir_id) {
-                        Some(Node::Local(hir::Local { hir_id, .. })) => *hir_id,
-                        Some(Node::Item(hir::Item { owner_id, .. })) => {
-                            cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id)
-                        },
-                        _ => unreachable!(),
-                    };
-
-                    // if unsafe block is part of a let/const/static statement,
-                    // and accept_comment_above_statement is set to true
-                    // we accept the safety comment in the line the precedes this statement.
-                    accept_comment_above_statement
-                        && span_with_attrs_in_body_has_safety_comment(
-                            cx,
-                            *span,
-                            hir_id,
-                            accept_comment_above_attributes,
-                        )
-                } else {
-                    !is_branchy(expr)
-                        && span_with_attrs_in_body_has_safety_comment(
-                            cx,
-                            expr.span,
-                            expr.hir_id,
-                            accept_comment_above_attributes,
-                        )
-                }
+        let (span, hir_id) = match node {
+            Node::Expr(expr) => match get_parent_node(cx.tcx, expr.hir_id) {
+                Some(Node::Local(hir::Local { span, hir_id, .. })) => (*span, *hir_id),
+                Some(Node::Item(hir::Item {
+                    kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+                    span,
+                    owner_id,
+                    ..
+                })) => (*span, cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id)),
+                _ => {
+                    if is_branchy(expr) {
+                        return false;
+                    }
+                    (expr.span, expr.hir_id)
+                },
             },
             Node::Stmt(hir::Stmt {
                 kind:
@@ -387,28 +364,27 @@ fn block_parents_have_safety_comment(
                     | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }),
                 ..
             })
-            | Node::Local(hir::Local { span, hir_id, .. }) => {
-                span_with_attrs_in_body_has_safety_comment(cx, *span, *hir_id, accept_comment_above_attributes)
-            },
+            | Node::Local(hir::Local { span, hir_id, .. }) => (*span, *hir_id),
             Node::Item(hir::Item {
                 kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
                 span,
                 owner_id,
                 ..
-            }) => span_with_attrs_in_body_has_safety_comment(
-                cx,
-                *span,
-                cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id),
-                accept_comment_above_attributes,
-            ),
-            _ => false,
+            }) => (*span, cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id)),
+            _ => return false,
         };
+        // if unsafe block is part of a let/const/static statement,
+        // and accept_comment_above_statement is set to true
+        // we accept the safety comment in the line the precedes this statement.
+        accept_comment_above_statement
+            && span_with_attrs_has_safety_comment(cx, span, hir_id, accept_comment_above_attributes)
+    } else {
+        false
     }
-    false
 }
 
 /// Extends `span` to also include its attributes, then checks if that span has a safety comment.
-fn span_with_attrs_in_body_has_safety_comment(
+fn span_with_attrs_has_safety_comment(
     cx: &LateContext<'_>,
     span: Span,
     hir_id: HirId,
@@ -420,7 +396,7 @@ fn span_with_attrs_in_body_has_safety_comment(
         span
     };
 
-    span_in_body_has_safety_comment(cx, span)
+    span_has_safety_comment(cx, span)
 }
 
 /// Checks if an expression is "branchy", e.g. loop, match/if/etc.
@@ -444,7 +420,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
     matches!(
         span_from_macro_expansion_has_safety_comment(cx, span),
         HasSafetyComment::Yes(_)
-    ) || span_in_body_has_safety_comment(cx, span)
+    ) || span_has_safety_comment(cx, span)
 }
 
 fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span {
@@ -633,29 +609,36 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
     let body = cx.enclosing_body?;
     let map = cx.tcx.hir();
     let mut span = map.body(body).value.span;
+    let mut maybe_global_var = false;
     for (_, node) in map.parent_iter(body.hir_id) {
         match node {
             Node::Expr(e) => span = e.span,
-            Node::Block(_)
-            | Node::Arm(_)
-            | Node::Stmt(_)
-            | Node::Local(_)
-            | Node::Item(hir::Item {
+            Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::Local(_) => (),
+            Node::Item(hir::Item {
                 kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
                 ..
-            }) => (),
+            }) => maybe_global_var = true,
+            Node::Item(hir::Item {
+                kind: hir::ItemKind::Mod(_),
+                span: item_span,
+                ..
+            }) => {
+                span = *item_span;
+                break;
+            },
+            Node::Crate(mod_) if maybe_global_var => {
+                span = mod_.spans.inner_span;
+            },
             _ => break,
         }
     }
     Some(span)
 }
 
-fn span_in_body_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
+fn span_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
     let source_map = cx.sess().source_map();
     let ctxt = span.ctxt();
-    if ctxt == SyntaxContext::root()
-        && let Some(search_span) = get_body_search_span(cx)
-    {
+    if ctxt.is_root() && let Some(search_span) = get_body_search_span(cx) {
         if let Ok(unsafe_line) = source_map.lookup_line(span.lo())
             && let Some(body_span) = walk_span_to_context(search_span, SyntaxContext::root())
             && let Ok(body_line) = source_map.lookup_line(body_span.lo())
diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs
index dd829ded0d0..de4b8738e35 100644
--- a/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/clippy_lints/src/unit_return_expecting_ord.rs
@@ -26,7 +26,7 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// ```rust
-    /// let mut twins = vec!((1, 1), (2, 2));
+    /// let mut twins = vec![(1, 1), (2, 2)];
     /// twins.sort_by_key(|x| { x.1; });
     /// ```
     #[clippy::version = "1.47.0"]
diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs
index c99b0290c0c..9a0d83d83f1 100644
--- a/clippy_lints/src/unwrap.rs
+++ b/clippy_lints/src/unwrap.rs
@@ -1,15 +1,18 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::usage::is_potentially_mutated;
+use clippy_utils::usage::is_potentially_local_place;
 use clippy_utils::{higher, path_to_local};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
-use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, PathSegment, UnOp};
+use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegment, UnOp};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceWithHirId};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::Ty;
+use rustc_middle::mir::FakeReadCause;
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map::Span;
@@ -192,6 +195,55 @@ fn collect_unwrap_info<'tcx>(
     Vec::new()
 }
 
+/// A HIR visitor delegate that checks if a local variable of type `Option<_>` is mutated,
+/// *except* for if `Option::as_mut` is called.
+/// The reason for why we allow that one specifically is that `.as_mut()` cannot change
+/// the option to `None`, and that is important because this lint relies on the fact that
+/// `is_some` + `unwrap` is equivalent to `if let Some(..) = ..`, which it would not be if
+/// the option is changed to None between `is_some` and `unwrap`.
+/// (And also `.as_mut()` is a somewhat common method that is still worth linting on.)
+struct MutationVisitor<'tcx> {
+    is_mutated: bool,
+    local_id: HirId,
+    tcx: TyCtxt<'tcx>,
+}
+
+/// Checks if the parent of the expression pointed at by the given `HirId` is a call to
+/// `Option::as_mut`.
+///
+/// Used by the mutation visitor to specifically allow `.as_mut()` calls.
+/// In particular, the `HirId` that the visitor receives is the id of the local expression
+/// (i.e. the `x` in `x.as_mut()`), and that is the reason for why we care about its parent
+/// expression: that will be where the actual method call is.
+fn is_option_as_mut_use(tcx: TyCtxt<'_>, expr_id: HirId) -> bool {
+    if let Node::Expr(mutating_expr) = tcx.hir().get_parent(expr_id)
+        && let ExprKind::MethodCall(path, ..) = mutating_expr.kind
+    {
+        path.ident.name.as_str() == "as_mut"
+    } else {
+        false
+    }
+}
+
+impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> {
+    fn borrow(&mut self, cat: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
+        if let ty::BorrowKind::MutBorrow = bk
+            && is_potentially_local_place(self.local_id, &cat.place)
+            && !is_option_as_mut_use(self.tcx, diag_expr_id)
+        {
+            self.is_mutated = true;
+        }
+    }
+
+    fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {
+        self.is_mutated = true;
+    }
+
+    fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
+
+    fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+}
+
 impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
     fn visit_branch(
         &mut self,
@@ -202,10 +254,26 @@ impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
     ) {
         let prev_len = self.unwrappables.len();
         for unwrap_info in collect_unwrap_info(self.cx, if_expr, cond, branch, else_branch, true) {
-            if is_potentially_mutated(unwrap_info.local_id, cond, self.cx)
-                || is_potentially_mutated(unwrap_info.local_id, branch, self.cx)
-            {
-                // if the variable is mutated, we don't know whether it can be unwrapped:
+            let mut delegate = MutationVisitor {
+                tcx: self.cx.tcx,
+                is_mutated: false,
+                local_id: unwrap_info.local_id,
+            };
+
+            let infcx = self.cx.tcx.infer_ctxt().build();
+            let mut vis = ExprUseVisitor::new(
+                &mut delegate,
+                &infcx,
+                cond.hir_id.owner.def_id,
+                self.cx.param_env,
+                self.cx.typeck_results(),
+            );
+            vis.walk_expr(cond);
+            vis.walk_expr(branch);
+
+            if delegate.is_mutated {
+                // if the variable is mutated, we don't know whether it can be unwrapped.
+                // it might have been changed to `None` in between `is_some` + `unwrap`.
                 continue;
             }
             self.unwrappables.push(unwrap_info);
@@ -215,6 +283,27 @@ impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
     }
 }
 
+enum AsRefKind {
+    AsRef,
+    AsMut,
+}
+
+/// Checks if the expression is a method call to `as_{ref,mut}` and returns the receiver of it.
+/// If it isn't, the expression itself is returned.
+fn consume_option_as_ref<'tcx>(expr: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, Option<AsRefKind>) {
+    if let ExprKind::MethodCall(path, recv, ..) = expr.kind {
+        if path.ident.name == sym::as_ref {
+            (recv, Some(AsRefKind::AsRef))
+        } else if path.ident.name.as_str() == "as_mut" {
+            (recv, Some(AsRefKind::AsMut))
+        } else {
+            (expr, None)
+        }
+    } else {
+        (expr, None)
+    }
+}
+
 impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
@@ -233,6 +322,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
             // find `unwrap[_err]()` calls:
             if_chain! {
                 if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind;
+                let (self_arg, as_ref_kind) = consume_option_as_ref(self_arg);
                 if let Some(id) = path_to_local(self_arg);
                 if [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name);
                 let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name);
@@ -268,7 +358,12 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
                                         unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()),
                                         "try",
                                         format!(
-                                            "if let {suggested_pattern} = {unwrappable_variable_name}",
+                                            "if let {suggested_pattern} = {borrow_prefix}{unwrappable_variable_name}",
+                                            borrow_prefix = match as_ref_kind {
+                                                Some(AsRefKind::AsRef) => "&",
+                                                Some(AsRefKind::AsMut) => "&mut ",
+                                                None => "",
+                                            },
                                         ),
                                         // We don't track how the unwrapped value is used inside the
                                         // block or suggest deleting the unwrap, so we can't offer a
diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs
index 58ae0656db7..26889475522 100644
--- a/clippy_lints/src/utils/conf.rs
+++ b/clippy_lints/src/utils/conf.rs
@@ -561,6 +561,26 @@ define_Conf! {
     /// Which crates to allow absolute paths from
     (absolute_paths_allowed_crates: rustc_data_structures::fx::FxHashSet<String> =
         rustc_data_structures::fx::FxHashSet::default()),
+    /// Lint: EXPLICIT_ITER_LOOP
+    ///
+    /// Whether to recommend using implicit into iter for reborrowed values.
+    ///
+    /// #### Example
+    /// ```
+    /// let mut vec = vec![1, 2, 3];
+    /// let rmvec = &mut vec;
+    /// for _ in rmvec.iter() {}
+    /// for _ in rmvec.iter_mut() {}
+    /// ```
+    ///
+    /// Use instead:
+    /// ```
+    /// let mut vec = vec![1, 2, 3];
+    /// let rmvec = &mut vec;
+    /// for _ in &*rmvec {}
+    /// for _ in &mut *rmvec {}
+    /// ```
+    (enforce_iter_loop_reborrow: bool = false),
 }
 
 /// Search for the configuration file.
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 6c4cec59524..4ef3ec19647 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -5,6 +5,7 @@
 #![feature(lint_reasons)]
 #![feature(never_type)]
 #![feature(rustc_private)]
+#![feature(assert_matches)]
 #![recursion_limit = "512"]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
@@ -110,6 +111,7 @@ use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, Span};
 use rustc_target::abi::Integer;
+use visitors::Visitable;
 
 use crate::consts::{constant, miri_to_const, Constant};
 use crate::higher::Range;
@@ -1286,7 +1288,7 @@ pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<
 }
 
 /// Returns `true` if `expr` contains a return expression
-pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
+pub fn contains_return<'tcx>(expr: impl Visitable<'tcx>) -> bool {
     for_each_expr(expr, |e| {
         if matches!(e.kind, hir::ExprKind::Ret(..)) {
             ControlFlow::Break(())
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index a567c5cbdc9..2fb24b5c7ed 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -49,6 +49,7 @@ pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
 pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
 pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
+pub const ITER_ONCE: [&str; 5] = ["core", "iter", "sources", "once", "Once"];
 pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 #[cfg(feature = "internal")]
 pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
@@ -163,3 +164,4 @@ pub const DEBUG_STRUCT: [&str; 4] = ["core", "fmt", "builders", "DebugStruct"];
 pub const ORD_CMP: [&str; 4] = ["core", "cmp", "Ord", "cmp"];
 #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so
 pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];
+pub const ARRAY_INTO_ITER: [&str; 4] = ["core", "array", "iter", "IntoIter"];
diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs
index 600cd084c19..31cb421095e 100644
--- a/clippy_utils/src/source.rs
+++ b/clippy_utils/src/source.rs
@@ -362,7 +362,7 @@ pub fn snippet_block_with_context<'a>(
 }
 
 /// Same as `snippet_with_applicability`, but first walks the span up to the given context. This
-/// will result in the macro call, rather then the expansion, if the span is from a child context.
+/// will result in the macro call, rather than the expansion, if the span is from a child context.
 /// If the span is not from a child context, it will be used directly instead.
 ///
 /// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node
diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs
index ee5a49a2073..ae8ee371ffa 100644
--- a/clippy_utils/src/sugg.rs
+++ b/clippy_utils/src/sugg.rs
@@ -88,7 +88,7 @@ impl<'a> Sugg<'a> {
     }
 
     /// Same as `hir`, but first walks the span up to the given context. This will result in the
-    /// macro call, rather then the expansion, if the span is from a child context. If the span is
+    /// macro call, rather than the expansion, if the span is from a child context. If the span is
     /// not from a child context, it will be used directly instead.
     ///
     /// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index a05f682aa8c..f0b4ede35fb 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -27,6 +27,7 @@ use rustc_target::abi::{Size, VariantIdx};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::{Obligation, ObligationCause};
+use std::assert_matches::debug_assert_matches;
 use std::iter;
 
 use crate::{match_def_path, path_res, paths};
@@ -259,7 +260,11 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
             })),
     );
 
-    debug_assert_eq!(tcx.def_kind(trait_id), DefKind::Trait);
+    debug_assert_matches!(
+        tcx.def_kind(trait_id),
+        DefKind::Trait | DefKind::TraitAlias,
+        "`DefId` must belong to a trait or trait alias"
+    );
     #[cfg(debug_assertions)]
     assert_generic_args_match(tcx, trait_id, trait_ref.args);
 
diff --git a/clippy_utils/src/ty/type_certainty/mod.rs b/clippy_utils/src/ty/type_certainty/mod.rs
index 06fd9529044..dc7756533ac 100644
--- a/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/clippy_utils/src/ty/type_certainty/mod.rs
@@ -150,7 +150,7 @@ fn generic_args_certainty(cx: &LateContext<'_>, args: &GenericArgs<'_>) -> Certa
 }
 
 /// Tries to tell whether a `QPath` resolves to something certain, e.g., whether all of its path
-/// segments generic arguments are are instantiated.
+/// segments generic arguments are instantiated.
 ///
 /// `qpath` could refer to either a type or a value. The heuristic never needs the `DefId` of a
 /// value. So `DefId`s are retained only when `resolves_to_type` is true.
diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs
index 39ef76348d7..ec131c7f6a3 100644
--- a/clippy_utils/src/usage.rs
+++ b/clippy_utils/src/usage.rs
@@ -4,7 +4,7 @@ use core::ops::ControlFlow;
 use hir::def::Res;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir, Expr, ExprKind, HirId, HirIdSet};
-use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, Place, PlaceBase, PlaceWithHirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
@@ -37,6 +37,17 @@ pub fn is_potentially_mutated<'tcx>(variable: HirId, expr: &'tcx Expr<'_>, cx: &
     mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&variable))
 }
 
+pub fn is_potentially_local_place(local_id: HirId, place: &Place<'_>) -> bool {
+    match place.base {
+        PlaceBase::Local(id) => id == local_id,
+        PlaceBase::Upvar(_) => {
+            // Conservatively assume yes.
+            true
+        },
+        _ => false,
+    }
+}
+
 struct MutVarsDelegate {
     used_mutably: HirIdSet,
     skip: bool,
diff --git a/rust-toolchain b/rust-toolchain
index 19c09b58b98..9f5116eb73b 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-08-24"
+channel = "nightly-2023-09-07"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index c1c3d4a868f..9fcc269dbf8 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -4,7 +4,7 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(unused_extern_crates)]
 
-use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, Mode, OutputConflictHandling, RustfixMode};
+use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, Mode, OutputConflictHandling};
 
 use std::collections::BTreeMap;
 use std::env::{self, set_var, var_os};
@@ -114,36 +114,26 @@ fn canonicalize(path: impl AsRef<Path>) -> PathBuf {
 }
 
 fn base_config(test_dir: &str) -> (Config, Args) {
-    let bless = var_os("RUSTC_BLESS").is_some_and(|v| v != "0") || env::args().any(|arg| arg == "--bless");
-
-    let args = Args {
-        filters: env::var("TESTNAME")
-            .map(|filters| filters.split(',').map(str::to_string).collect())
-            .unwrap_or_default(),
-        quiet: false,
-        check: !bless,
-        threads: match std::env::var_os("RUST_TEST_THREADS") {
-            Some(n) => n.to_str().unwrap().parse().unwrap(),
-            None => std::thread::available_parallelism().unwrap(),
-        },
-        skip: Vec::new(),
-    };
+    let mut args = Args::test().unwrap();
+    args.bless |= var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
 
     let mut config = Config {
         mode: Mode::Yolo {
-            rustfix: RustfixMode::Everything,
+            rustfix: ui_test::RustfixMode::Everything,
         },
         stderr_filters: vec![(Match::PathBackslash, b"/")],
         stdout_filters: vec![],
-        output_conflict_handling: if bless {
-            OutputConflictHandling::Bless
-        } else {
-            OutputConflictHandling::Error("cargo uibless".into())
-        },
+        filter_files: env::var("TESTNAME")
+            .map(|filters| filters.split(',').map(str::to_string).collect())
+            .unwrap_or_default(),
         target: None,
         out_dir: canonicalize(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())).join("ui_test"),
         ..Config::rustc(Path::new("tests").join(test_dir))
     };
+    config.with_args(&args, /* bless by default */ false);
+    if let OutputConflictHandling::Error(err) = &mut config.output_conflict_handling {
+        *err = "cargo uibless".into();
+    }
     let current_exe_path = env::current_exe().unwrap();
     let deps_path = current_exe_path.parent().unwrap();
     let profile_path = deps_path.parent().unwrap();
@@ -186,7 +176,6 @@ fn run_ui() {
 
     ui_test::run_tests_generic(
         vec![config],
-        args,
         ui_test::default_file_filter,
         ui_test::default_per_file_config,
         if quiet {
@@ -211,7 +200,6 @@ fn run_internal_tests() {
 
     ui_test::run_tests_generic(
         vec![config],
-        args,
         ui_test::default_file_filter,
         ui_test::default_per_file_config,
         if quiet {
@@ -245,7 +233,6 @@ fn run_ui_toml() {
 
     ui_test::run_tests_generic(
         vec![config],
-        args,
         ui_test::default_file_filter,
         |config, path, _file_contents| {
             config
@@ -302,10 +289,16 @@ fn run_ui_cargo() {
 
     let quiet = args.quiet;
 
+    let ignored_32bit = |path: &Path| {
+        // FIXME: for some reason the modules are linted in a different order for this test
+        cfg!(target_pointer_width = "32") && path.ends_with("tests/ui-cargo/module_style/fail_mod/Cargo.toml")
+    };
+
     ui_test::run_tests_generic(
         vec![config],
-        args,
-        |path, args, _config| path.ends_with("Cargo.toml") && ui_test::default_filter_by_arg(path, args),
+        |path, config| {
+            path.ends_with("Cargo.toml") && ui_test::default_any_file_filter(path, config) && !ignored_32bit(path)
+        },
         |config, path, _file_contents| {
             config.out_dir = canonicalize(
                 std::env::current_dir()
diff --git a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr
index e161507b533..4d97d54963d 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr
@@ -1,6 +1,7 @@
 error: package `cargo_common_metadata_fail` is missing `package.description` metadata
   |
   = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::cargo_common_metadata)]`
 
 error: package `cargo_common_metadata_fail` is missing `either package.license or package.license_file` metadata
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr
index dbf494cc342..9eb884f0890 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr
@@ -1,6 +1,7 @@
 error: package `cargo_common_metadata_fail_publish` is missing `package.description` metadata
   |
   = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::cargo_common_metadata)]`
 
 error: package `cargo_common_metadata_fail_publish` is missing `either package.license or package.license_file` metadata
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr
index ae5967406f6..f9685a784a3 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr
@@ -1,6 +1,7 @@
 error: package `cargo_common_metadata_fail_publish_true` is missing `package.description` metadata
   |
   = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::cargo_common_metadata)]`
 
 error: package `cargo_common_metadata_fail_publish_true` is missing `either package.license or package.license_file` metadata
 
diff --git a/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr b/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr
index fde3a1e6599..912ea9bb4d1 100644
--- a/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr
+++ b/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr
@@ -9,6 +9,7 @@ error: file is loaded as a module multiple times: `src/b.rs`
   |
   = help: replace all but one `mod` item with `use` items
   = note: `-D clippy::duplicate-mod` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::duplicate_mod)]`
 
 error: file is loaded as a module multiple times: `src/c.rs`
   --> src/main.rs:9:1
diff --git a/tests/ui-cargo/feature_name/fail/Cargo.stderr b/tests/ui-cargo/feature_name/fail/Cargo.stderr
index da2db45d3b8..388f49fb213 100644
--- a/tests/ui-cargo/feature_name/fail/Cargo.stderr
+++ b/tests/ui-cargo/feature_name/fail/Cargo.stderr
@@ -2,6 +2,7 @@ error: the "no-" prefix in the feature name "no-qaq" is negative
   |
   = help: consider renaming the feature to "qaq", but make sure the feature adds functionality
   = note: `-D clippy::negative-feature-names` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::negative_feature_names)]`
 
 error: the "no_" prefix in the feature name "no_qaq" is negative
   |
@@ -19,6 +20,7 @@ error: the "-support" suffix in the feature name "qvq-support" is redundant
   |
   = help: consider renaming the feature to "qvq"
   = note: `-D clippy::redundant-feature-names` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::redundant_feature_names)]`
 
 error: the "_support" suffix in the feature name "qvq_support" is redundant
   |
diff --git a/tests/ui-cargo/module_style/fail_mod/Cargo.stderr b/tests/ui-cargo/module_style/fail_mod/Cargo.stderr
index c2907f319e6..902330e1785 100644
--- a/tests/ui-cargo/module_style/fail_mod/Cargo.stderr
+++ b/tests/ui-cargo/module_style/fail_mod/Cargo.stderr
@@ -6,6 +6,7 @@ error: `mod.rs` files are required, found `src/bad/inner.rs`
   |
   = help: move `src/bad/inner.rs` to `src/bad/inner/mod.rs`
   = note: `-D clippy::self-named-module-files` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::self_named_module_files)]`
 
 error: `mod.rs` files are required, found `src/bad/inner/stuff.rs`
  --> src/bad/inner/stuff.rs:1:1
diff --git a/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr b/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr
index fcf1a3c5e66..d776feb7f2e 100644
--- a/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr
+++ b/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr
@@ -6,5 +6,6 @@ error: `mod.rs` files are required, found `src/bad.rs`
   |
   = help: move `src/bad.rs` to `src/bad/mod.rs`
   = note: `-D clippy::self-named-module-files` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::self_named_module_files)]`
 
 error: could not compile `fail-mod-remap` (bin "fail-mod-remap") due to previous error
diff --git a/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr b/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr
index f61642ca2ef..22558bc4ce8 100644
--- a/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr
+++ b/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr
@@ -6,5 +6,6 @@ error: `mod.rs` files are not allowed, found `src/bad/mod.rs`
   |
   = help: move `src/bad/mod.rs` to `src/bad.rs`
   = note: `-D clippy::mod-module-files` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::mod_module_files)]`
 
 error: could not compile `fail-no-mod` (bin "fail-no-mod") due to previous error
diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr
index 5bcce920455..4beedc10830 100644
--- a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr
+++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr
@@ -1,5 +1,6 @@
 error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9
   |
   = note: `-D clippy::multiple-crate-versions` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::multiple_crate_versions)]`
 
 error: could not compile `multiple_crate_versions` (bin "multiple_crate_versions") due to previous error
diff --git a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr
index b1578c9f324..65a19bb0718 100644
--- a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr
+++ b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr
@@ -1,5 +1,6 @@
 error: wildcard dependency for `regex`
   |
   = note: `-D clippy::wildcard-dependencies` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::wildcard_dependencies)]`
 
 error: could not compile `wildcard_dependencies` (bin "wildcard_dependencies") due to previous error
diff --git a/tests/ui-internal/check_formulation.stderr b/tests/ui-internal/check_formulation.stderr
index 10eabca4b9d..96fa617601f 100644
--- a/tests/ui-internal/check_formulation.stderr
+++ b/tests/ui-internal/check_formulation.stderr
@@ -6,6 +6,7 @@ LL |     /// Check for lint formulations that are correct
    |
    = help: try using `Checks for` instead
    = note: `-D clippy::almost-standard-lint-formulation` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::almost_standard_lint_formulation)]`
 
 error: non-standard lint formulation
   --> $DIR/check_formulation.rs:33:5
diff --git a/tests/ui-internal/if_chain_style.stderr b/tests/ui-internal/if_chain_style.stderr
index b12df278652..ea04955323d 100644
--- a/tests/ui-internal/if_chain_style.stderr
+++ b/tests/ui-internal/if_chain_style.stderr
@@ -16,6 +16,7 @@ help: this `let` statement can also be in the `if_chain!`
 LL |         let x = "";
    |         ^^^^^^^^^^^
    = note: `-D clippy::if-chain-style` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::if_chain_style)]`
 
 error: `if a && b;` should be `if a; if b;`
   --> $DIR/if_chain_style.rs:24:12
diff --git a/tests/ui-internal/invalid_paths.stderr b/tests/ui-internal/invalid_paths.stderr
index 0e850886917..988d32d5259 100644
--- a/tests/ui-internal/invalid_paths.stderr
+++ b/tests/ui-internal/invalid_paths.stderr
@@ -5,6 +5,7 @@ LL |     pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::invalid-paths` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::invalid_paths)]`
 
 error: invalid path
   --> $DIR/invalid_paths.rs:18:5
diff --git a/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index 3ca45404e44..58b1fd92b5d 100644
--- a/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -6,6 +6,7 @@ LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
    |
    = help: convert all references to use `sym::Deref`
    = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::unnecessary_def_path)]`
 
 error: hardcoded path to a language item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
diff --git a/tests/ui-toml/disallowed_macros/auxiliary/macros.rs b/tests/ui-toml/disallowed_macros/auxiliary/macros.rs
index fcaeace0e98..f4166b227fc 100644
--- a/tests/ui-toml/disallowed_macros/auxiliary/macros.rs
+++ b/tests/ui-toml/disallowed_macros/auxiliary/macros.rs
@@ -30,3 +30,18 @@ macro_rules! item {
         const ITEM: usize = 1;
     };
 }
+
+#[macro_export]
+macro_rules! binop {
+    ($t:tt) => {
+        $t + $t
+    };
+}
+
+#[macro_export]
+macro_rules! attr {
+    ($i:item) => {
+        #[repr(C)]
+        $i
+    };
+}
diff --git a/tests/ui-toml/disallowed_macros/clippy.toml b/tests/ui-toml/disallowed_macros/clippy.toml
index c8fe8be9a77..85f1b71eb66 100644
--- a/tests/ui-toml/disallowed_macros/clippy.toml
+++ b/tests/ui-toml/disallowed_macros/clippy.toml
@@ -8,4 +8,6 @@ disallowed-macros = [
     "macros::ty",
     "macros::pat",
     "macros::item",
+    "macros::binop",
+    "macros::attr",
 ]
diff --git a/tests/ui-toml/disallowed_macros/disallowed_macros.rs b/tests/ui-toml/disallowed_macros/disallowed_macros.rs
index ba919b48788..4a3d55e13c9 100644
--- a/tests/ui-toml/disallowed_macros/disallowed_macros.rs
+++ b/tests/ui-toml/disallowed_macros/disallowed_macros.rs
@@ -20,11 +20,14 @@ fn main() {
     let macros::pat!() = 1;
     let _: macros::ty!() = "";
     macros::item!();
+    let _ = macros::binop!(1);
 
     eprintln!("allowed");
 }
 
-struct S;
+macros::attr! {
+    struct S;
+}
 
 impl S {
     macros::item!();
diff --git a/tests/ui-toml/disallowed_macros/disallowed_macros.stderr b/tests/ui-toml/disallowed_macros/disallowed_macros.stderr
index 0eebd587a5f..3c6f59b16e7 100644
--- a/tests/ui-toml/disallowed_macros/disallowed_macros.stderr
+++ b/tests/ui-toml/disallowed_macros/disallowed_macros.stderr
@@ -63,23 +63,37 @@ error: use of a disallowed macro `macros::item`
 LL |     macros::item!();
    |     ^^^^^^^^^^^^^^^
 
+error: use of a disallowed macro `macros::binop`
+  --> $DIR/disallowed_macros.rs:23:13
+   |
+LL |     let _ = macros::binop!(1);
+   |             ^^^^^^^^^^^^^^^^^
+
+error: use of a disallowed macro `macros::attr`
+  --> $DIR/disallowed_macros.rs:28:1
+   |
+LL | / macros::attr! {
+LL | |     struct S;
+LL | | }
+   | |_^
+
 error: use of a disallowed macro `macros::item`
-  --> $DIR/disallowed_macros.rs:30:5
+  --> $DIR/disallowed_macros.rs:33:5
    |
 LL |     macros::item!();
    |     ^^^^^^^^^^^^^^^
 
 error: use of a disallowed macro `macros::item`
-  --> $DIR/disallowed_macros.rs:34:5
+  --> $DIR/disallowed_macros.rs:37:5
    |
 LL |     macros::item!();
    |     ^^^^^^^^^^^^^^^
 
 error: use of a disallowed macro `macros::item`
-  --> $DIR/disallowed_macros.rs:38:5
+  --> $DIR/disallowed_macros.rs:41:5
    |
 LL |     macros::item!();
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to 13 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs
deleted file mode 100644
index 60fbaaea3d3..00000000000
--- a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs
+++ /dev/null
@@ -1,469 +0,0 @@
-// NOTE: Copied from `ui/auxiliary/proc_macros.rs`, couldn't get `../` to work for some reason
-
-#![feature(let_chains)]
-#![feature(proc_macro_span)]
-#![allow(clippy::excessive_nesting, dead_code)]
-
-extern crate proc_macro;
-
-use core::mem;
-use proc_macro::token_stream::IntoIter;
-use proc_macro::Delimiter::{self, Brace, Parenthesis};
-use proc_macro::Spacing::{self, Alone, Joint};
-use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree as TT};
-
-type Result<T> = core::result::Result<T, TokenStream>;
-
-/// Make a `compile_error!` pointing to the given span.
-fn make_error(msg: &str, span: Span) -> TokenStream {
-    TokenStream::from_iter([
-        TT::Ident(Ident::new("compile_error", span)),
-        TT::Punct(punct_with_span('!', Alone, span)),
-        TT::Group({
-            let mut msg = Literal::string(msg);
-            msg.set_span(span);
-            group_with_span(Parenthesis, TokenStream::from_iter([TT::Literal(msg)]), span)
-        }),
-    ])
-}
-
-fn expect_tt<T>(tt: Option<TT>, f: impl FnOnce(TT) -> Option<T>, expected: &str, span: Span) -> Result<T> {
-    match tt {
-        None => Err(make_error(
-            &format!("unexpected end of input, expected {expected}"),
-            span,
-        )),
-        Some(tt) => {
-            let span = tt.span();
-            match f(tt) {
-                Some(x) => Ok(x),
-                None => Err(make_error(&format!("unexpected token, expected {expected}"), span)),
-            }
-        },
-    }
-}
-
-fn punct_with_span(c: char, spacing: Spacing, span: Span) -> Punct {
-    let mut p = Punct::new(c, spacing);
-    p.set_span(span);
-    p
-}
-
-fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Group {
-    let mut g = Group::new(delimiter, stream);
-    g.set_span(span);
-    g
-}
-
-/// Token used to escape the following token from the macro's span rules.
-const ESCAPE_CHAR: char = '$';
-
-/// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their
-/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
-#[proc_macro]
-pub fn with_span(input: TokenStream) -> TokenStream {
-    let mut iter = input.into_iter();
-    let span = iter.next().unwrap().span();
-    let mut res = TokenStream::new();
-    if let Err(e) = write_with_span(span, iter, &mut res) {
-        e
-    } else {
-        res
-    }
-}
-
-/// Takes a sequence of tokens and return the tokens with the span set such that they appear to be
-/// from an external macro. Tokens may be escaped with either `#ident` or `#(tokens)`.
-#[proc_macro]
-pub fn external(input: TokenStream) -> TokenStream {
-    let mut res = TokenStream::new();
-    if let Err(e) = write_with_span(Span::mixed_site(), input.into_iter(), &mut res) {
-        e
-    } else {
-        res
-    }
-}
-
-/// Copies all the tokens, replacing all their spans with the given span. Tokens can be escaped
-/// either by `#ident` or `#(tokens)`.
-fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Result<()> {
-    while let Some(tt) = input.next() {
-        match tt {
-            TT::Punct(p) if p.as_char() == ESCAPE_CHAR => {
-                expect_tt(
-                    input.next(),
-                    |tt| match tt {
-                        tt @ (TT::Ident(_) | TT::Literal(_)) => {
-                            out.extend([tt]);
-                            Some(())
-                        },
-                        TT::Punct(mut p) if p.as_char() == ESCAPE_CHAR => {
-                            p.set_span(s);
-                            out.extend([TT::Punct(p)]);
-                            Some(())
-                        },
-                        TT::Group(g) if g.delimiter() == Parenthesis => {
-                            out.extend([TT::Group(group_with_span(Delimiter::None, g.stream(), g.span()))]);
-                            Some(())
-                        },
-                        _ => None,
-                    },
-                    "an ident, a literal, or parenthesized tokens",
-                    p.span(),
-                )?;
-            },
-            TT::Group(g) => {
-                let mut stream = TokenStream::new();
-                write_with_span(s, g.stream().into_iter(), &mut stream)?;
-                out.extend([TT::Group(group_with_span(g.delimiter(), stream, s))]);
-            },
-            mut tt => {
-                tt.set_span(s);
-                out.extend([tt]);
-            },
-        }
-    }
-    Ok(())
-}
-
-/// Within the item this attribute is attached to, an `inline!` macro is available which expands the
-/// contained tokens as though they came from a macro expansion.
-///
-/// Within the `inline!` macro, any token preceded by `$` is passed as though it were an argument
-/// with an automatically chosen fragment specifier. `$ident` will be passed as `ident`, `$1` or
-/// `$"literal"` will be passed as `literal`, `$'lt` will be passed as `lifetime`, and `$(...)` will
-/// pass the contained tokens as a `tt` sequence (the wrapping parenthesis are removed). If another
-/// specifier is required it can be specified within parenthesis like `$(@expr ...)`. This will
-/// expand the remaining tokens as a single argument.
-///
-/// Multiple `inline!` macros may be nested within each other. This will expand as nested macro
-/// calls. However, any arguments will be passed as though they came from the outermost context.
-#[proc_macro_attribute]
-pub fn inline_macros(args: TokenStream, input: TokenStream) -> TokenStream {
-    let mut args = args.into_iter();
-    let mac_name = match args.next() {
-        Some(TT::Ident(name)) => Some(name),
-        Some(tt) => {
-            return make_error(
-                "unexpected argument, expected either an ident or no arguments",
-                tt.span(),
-            );
-        },
-        None => None,
-    };
-    if let Some(tt) = args.next() {
-        return make_error(
-            "unexpected argument, expected either an ident or no arguments",
-            tt.span(),
-        );
-    };
-
-    let mac_name = if let Some(mac_name) = mac_name {
-        Ident::new(&format!("__inline_mac_{mac_name}"), Span::call_site())
-    } else {
-        let mut input = match LookaheadIter::new(input.clone().into_iter()) {
-            Some(x) => x,
-            None => return input,
-        };
-        loop {
-            match input.next() {
-                None => break Ident::new("__inline_mac", Span::call_site()),
-                Some(TT::Ident(kind)) => match &*kind.to_string() {
-                    "impl" => break Ident::new("__inline_mac_impl", Span::call_site()),
-                    kind @ ("struct" | "enum" | "union" | "fn" | "mod" | "trait" | "type" | "const" | "static") => {
-                        if let TT::Ident(name) = &input.tt {
-                            break Ident::new(&format!("__inline_mac_{kind}_{name}"), Span::call_site());
-                        } else {
-                            break Ident::new(&format!("__inline_mac_{kind}"), Span::call_site());
-                        }
-                    },
-                    _ => {},
-                },
-                _ => {},
-            }
-        }
-    };
-
-    let mut expander = Expander::default();
-    let mut mac = MacWriter::new(mac_name);
-    if let Err(e) = expander.expand(input.into_iter(), &mut mac) {
-        return e;
-    }
-    let mut out = TokenStream::new();
-    mac.finish(&mut out);
-    out.extend(expander.expn);
-    out
-}
-
-/// Wraps a `TokenStream` iterator with a single token lookahead.
-struct LookaheadIter {
-    tt: TT,
-    iter: IntoIter,
-}
-impl LookaheadIter {
-    fn new(mut iter: IntoIter) -> Option<Self> {
-        iter.next().map(|tt| Self { tt, iter })
-    }
-
-    /// Get's the lookahead token, replacing it with the next token in the stream.
-    /// Note: If there isn't a next token, this will not return the lookahead token.
-    fn next(&mut self) -> Option<TT> {
-        self.iter.next().map(|tt| mem::replace(&mut self.tt, tt))
-    }
-}
-
-/// Builds the macro used to implement all the `inline!` macro calls.
-struct MacWriter {
-    name: Ident,
-    macros: TokenStream,
-    next_idx: usize,
-}
-impl MacWriter {
-    fn new(name: Ident) -> Self {
-        Self {
-            name,
-            macros: TokenStream::new(),
-            next_idx: 0,
-        }
-    }
-
-    /// Inserts a new `inline!` call.
-    fn insert(&mut self, name_span: Span, bang_span: Span, body: Group, expander: &mut Expander) -> Result<()> {
-        let idx = self.next_idx;
-        self.next_idx += 1;
-
-        let mut inner = Expander::for_arm(idx);
-        inner.expand(body.stream().into_iter(), self)?;
-        let new_arm = inner.arm.unwrap();
-
-        self.macros.extend([
-            TT::Group(Group::new(Parenthesis, new_arm.args_def)),
-            TT::Punct(Punct::new('=', Joint)),
-            TT::Punct(Punct::new('>', Alone)),
-            TT::Group(Group::new(Parenthesis, inner.expn)),
-            TT::Punct(Punct::new(';', Alone)),
-        ]);
-
-        expander.expn.extend([
-            TT::Ident({
-                let mut name = self.name.clone();
-                name.set_span(name_span);
-                name
-            }),
-            TT::Punct(punct_with_span('!', Alone, bang_span)),
-        ]);
-        let mut call_body = TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]);
-        if let Some(arm) = expander.arm.as_mut() {
-            if !new_arm.args.is_empty() {
-                arm.add_sub_args(new_arm.args, &mut call_body);
-            }
-        } else {
-            call_body.extend(new_arm.args);
-        }
-        let mut g = Group::new(body.delimiter(), call_body);
-        g.set_span(body.span());
-        expander.expn.extend([TT::Group(g)]);
-        Ok(())
-    }
-
-    /// Creates the macro definition.
-    fn finish(self, out: &mut TokenStream) {
-        if self.next_idx != 0 {
-            out.extend([
-                TT::Ident(Ident::new("macro_rules", Span::call_site())),
-                TT::Punct(Punct::new('!', Alone)),
-                TT::Ident(self.name),
-                TT::Group(Group::new(Brace, self.macros)),
-            ])
-        }
-    }
-}
-
-struct MacroArm {
-    args_def: TokenStream,
-    args: Vec<TT>,
-}
-impl MacroArm {
-    fn add_single_arg_def(&mut self, kind: &str, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
-        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
-        self.args_def.extend([
-            TT::Punct(Punct::new('$', Alone)),
-            TT::Ident(name.clone()),
-            TT::Punct(Punct::new(':', Alone)),
-            TT::Ident(Ident::new(kind, Span::call_site())),
-        ]);
-        name.set_span(arg_span);
-        out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]);
-    }
-
-    fn add_parenthesized_arg_def(&mut self, kind: Ident, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
-        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
-        self.args_def.extend([TT::Group(Group::new(
-            Parenthesis,
-            TokenStream::from_iter([
-                TT::Punct(Punct::new('$', Alone)),
-                TT::Ident(name.clone()),
-                TT::Punct(Punct::new(':', Alone)),
-                TT::Ident(kind),
-            ]),
-        ))]);
-        name.set_span(arg_span);
-        out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]);
-    }
-
-    fn add_multi_arg_def(&mut self, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
-        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
-        self.args_def.extend([TT::Group(Group::new(
-            Parenthesis,
-            TokenStream::from_iter([
-                TT::Punct(Punct::new('$', Alone)),
-                TT::Group(Group::new(
-                    Parenthesis,
-                    TokenStream::from_iter([
-                        TT::Punct(Punct::new('$', Alone)),
-                        TT::Ident(name.clone()),
-                        TT::Punct(Punct::new(':', Alone)),
-                        TT::Ident(Ident::new("tt", Span::call_site())),
-                    ]),
-                )),
-                TT::Punct(Punct::new('*', Alone)),
-            ]),
-        ))]);
-        name.set_span(arg_span);
-        out.extend([
-            TT::Punct(punct_with_span('$', Alone, dollar_span)),
-            TT::Group(group_with_span(
-                Parenthesis,
-                TokenStream::from_iter([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]),
-                dollar_span,
-            )),
-            TT::Punct(punct_with_span('*', Alone, dollar_span)),
-        ]);
-    }
-
-    fn add_arg(&mut self, dollar_span: Span, tt: TT, input: &mut IntoIter, out: &mut TokenStream) -> Result<()> {
-        match tt {
-            TT::Punct(p) if p.as_char() == ESCAPE_CHAR => out.extend([TT::Punct(p)]),
-            TT::Punct(p) if p.as_char() == '\'' && p.spacing() == Joint => {
-                let lt_name = expect_tt(
-                    input.next(),
-                    |tt| match tt {
-                        TT::Ident(x) => Some(x),
-                        _ => None,
-                    },
-                    "lifetime name",
-                    p.span(),
-                )?;
-                let arg_span = p.span().join(lt_name.span()).unwrap_or(p.span());
-                self.add_single_arg_def("lifetime", dollar_span, arg_span, out);
-                self.args.extend([TT::Punct(p), TT::Ident(lt_name)]);
-            },
-            TT::Ident(x) => {
-                self.add_single_arg_def("ident", dollar_span, x.span(), out);
-                self.args.push(TT::Ident(x));
-            },
-            TT::Literal(x) => {
-                self.add_single_arg_def("literal", dollar_span, x.span(), out);
-                self.args.push(TT::Literal(x));
-            },
-            TT::Group(g) if g.delimiter() == Parenthesis => {
-                let mut inner = g.stream().into_iter();
-                if let Some(TT::Punct(p)) = inner.next()
-                    && p.as_char() == '@'
-                {
-                    let kind = expect_tt(
-                        inner.next(),
-                        |tt| match tt {
-                            TT::Ident(kind) => Some(kind),
-                            _ => None,
-                        },
-                        "a macro fragment specifier",
-                        p.span(),
-                    )?;
-                    self.add_parenthesized_arg_def(kind, dollar_span, g.span(), out);
-                    self.args.push(TT::Group(group_with_span(Parenthesis, inner.collect(), g.span())))
-                } else {
-                    self.add_multi_arg_def(dollar_span, g.span(), out);
-                    self.args.push(TT::Group(g));
-                }
-            },
-            tt => return Err(make_error("unsupported escape", tt.span())),
-        };
-        Ok(())
-    }
-
-    fn add_sub_args(&mut self, args: Vec<TT>, out: &mut TokenStream) {
-        self.add_multi_arg_def(Span::call_site(), Span::call_site(), out);
-        self.args
-            .extend([TT::Group(Group::new(Parenthesis, TokenStream::from_iter(args)))]);
-    }
-}
-
-#[derive(Default)]
-struct Expander {
-    arm: Option<MacroArm>,
-    expn: TokenStream,
-}
-impl Expander {
-    fn for_arm(idx: usize) -> Self {
-        Self {
-            arm: Some(MacroArm {
-                args_def: TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]),
-                args: Vec::new(),
-            }),
-            expn: TokenStream::new(),
-        }
-    }
-
-    fn write_tt(&mut self, tt: TT, mac: &mut MacWriter) -> Result<()> {
-        match tt {
-            TT::Group(g) => {
-                let outer = mem::take(&mut self.expn);
-                self.expand(g.stream().into_iter(), mac)?;
-                let inner = mem::replace(&mut self.expn, outer);
-                self.expn
-                    .extend([TT::Group(group_with_span(g.delimiter(), inner, g.span()))]);
-            },
-            tt => self.expn.extend([tt]),
-        }
-        Ok(())
-    }
-
-    fn expand(&mut self, input: IntoIter, mac: &mut MacWriter) -> Result<()> {
-        let Some(mut input) = LookaheadIter::new(input) else {
-            return Ok(());
-        };
-        while let Some(tt) = input.next() {
-            if let TT::Punct(p) = &tt
-                && p.as_char() == ESCAPE_CHAR
-                && let Some(arm) = self.arm.as_mut()
-            {
-                arm.add_arg(p.span(), mem::replace(&mut input.tt, tt), &mut input.iter, &mut self.expn)?;
-                if input.next().is_none() {
-                    return Ok(());
-                }
-            } else if let TT::Punct(p) = &input.tt
-                && p.as_char() == '!'
-                && let TT::Ident(name) = &tt
-                && name.to_string() == "inline"
-            {
-                let g = expect_tt(
-                    input.iter.next(),
-                    |tt| match tt {
-                        TT::Group(g) => Some(g),
-                        _ => None,
-                    },
-                    "macro arguments",
-                    p.span(),
-                )?;
-                mac.insert(name.span(), p.span(), g, self)?;
-                if input.next().is_none() {
-                    return Ok(());
-                }
-            } else {
-                self.write_tt(tt, mac)?;
-            }
-        }
-        self.write_tt(input.tt, mac)
-    }
-}
diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs
index 25f0d0d6230..d737a832dd1 100644
--- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs
+++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:../../ui/auxiliary/proc_macros.rs
 #![rustfmt::skip]
 #![feature(custom_inner_attributes)]
 #![allow(unused)]
@@ -156,7 +156,7 @@ fn main() {
     for i in {{{{xx}}}} {{{{{{{{}}}}}}}}
 
     while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}}
-    
+
     while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}}
 
     let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} };
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index cdabe6460cd..b97bb144468 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -28,6 +28,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            disallowed-types
            doc-valid-idents
            enable-raw-pointer-heuristic-for-send
+           enforce-iter-loop-reborrow
            enforced-import-renames
            enum-variant-name-threshold
            enum-variant-size-threshold
@@ -99,6 +100,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            disallowed-types
            doc-valid-idents
            enable-raw-pointer-heuristic-for-send
+           enforce-iter-loop-reborrow
            enforced-import-renames
            enum-variant-name-threshold
            enum-variant-size-threshold
diff --git a/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs
deleted file mode 100644
index 1c591fc76f3..00000000000
--- a/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-extern crate proc_macro;
-
-use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree};
-
-#[proc_macro]
-pub fn unsafe_block(input: TokenStream) -> TokenStream {
-    let span = input.into_iter().next().unwrap().span();
-    TokenStream::from_iter([TokenTree::Ident(Ident::new("unsafe", span)), {
-        let mut group = Group::new(Delimiter::Brace, TokenStream::new());
-        group.set_span(span);
-        TokenTree::Group(group)
-    }])
-}
diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
index c0976f0d600..b28e1b7d180 100644
--- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
+++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_unsafe.rs
+//@aux-build:../../ui/auxiliary/proc_macro_unsafe.rs
 
 #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)]
 #![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)]
@@ -564,4 +564,18 @@ fn issue_8679<T: Copy>() {
     unsafe {}
 }
 
+mod issue_11246 {
+    // Safety: foo
+    const _: () = unsafe {};
+
+    // Safety: A safety comment
+    const FOO: () = unsafe {};
+
+    // Safety: bar
+    static BAR: u8 = unsafe { 0 };
+}
+
+// Safety: Another safety comment
+const FOO: () = unsafe {};
+
 fn main() {}
diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed
index db85247f47d..e3f2ca72d1c 100644
--- a/tests/ui/bool_comparison.fixed
+++ b/tests/ui/bool_comparison.fixed
@@ -1,6 +1,6 @@
 #![allow(clippy::needless_if)]
 #![warn(clippy::bool_comparison)]
-#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)]
+#![allow(clippy::non_canonical_partial_ord_impl)]
 
 fn main() {
     let x = true;
diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs
index 0915f88544b..d1bc20d6831 100644
--- a/tests/ui/bool_comparison.rs
+++ b/tests/ui/bool_comparison.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::needless_if)]
 #![warn(clippy::bool_comparison)]
-#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)]
+#![allow(clippy::non_canonical_partial_ord_impl)]
 
 fn main() {
     let x = true;
diff --git a/tests/ui/cast_size_32bit.stderr b/tests/ui/cast_size.32bit.stderr
similarity index 78%
rename from tests/ui/cast_size_32bit.stderr
rename to tests/ui/cast_size.32bit.stderr
index fb51783a487..379ca60862b 100644
--- a/tests/ui/cast_size_32bit.stderr
+++ b/tests/ui/cast_size.32bit.stderr
@@ -1,44 +1,46 @@
 error: casting `isize` to `i8` may truncate the value
-  --> $DIR/cast_size_32bit.rs:12:5
+  --> $DIR/cast_size.rs:15:5
    |
 LL |     1isize as i8;
    |     ^^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
    = note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]`
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     i8::try_from(1isize);
    |     ~~~~~~~~~~~~~~~~~~~~
 
 error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
-  --> $DIR/cast_size_32bit.rs:15:5
+  --> $DIR/cast_size.rs:18:5
    |
 LL |     x0 as f64;
    |     ^^^^^^^^^
    |
    = note: `-D clippy::cast-precision-loss` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]`
 
 error: casting `usize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`usize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
-  --> $DIR/cast_size_32bit.rs:16:5
+  --> $DIR/cast_size.rs:19:5
    |
 LL |     x1 as f64;
    |     ^^^^^^^^^
 
 error: casting `isize` to `f32` causes a loss of precision (`isize` is 32 or 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> $DIR/cast_size_32bit.rs:17:5
+  --> $DIR/cast_size.rs:20:5
    |
 LL |     x0 as f32;
    |     ^^^^^^^^^
 
 error: casting `usize` to `f32` causes a loss of precision (`usize` is 32 or 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> $DIR/cast_size_32bit.rs:18:5
+  --> $DIR/cast_size.rs:21:5
    |
 LL |     x1 as f32;
    |     ^^^^^^^^^
 
 error: casting `isize` to `i32` may truncate the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:19:5
+  --> $DIR/cast_size.rs:22:5
    |
 LL |     1isize as i32;
    |     ^^^^^^^^^^^^^
@@ -50,7 +52,7 @@ LL |     i32::try_from(1isize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:20:5
+  --> $DIR/cast_size.rs:23:5
    |
 LL |     1isize as u32;
    |     ^^^^^^^^^^^^^
@@ -62,7 +64,7 @@ LL |     u32::try_from(1isize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:21:5
+  --> $DIR/cast_size.rs:24:5
    |
 LL |     1usize as u32;
    |     ^^^^^^^^^^^^^
@@ -74,7 +76,7 @@ LL |     u32::try_from(1usize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:22:5
+  --> $DIR/cast_size.rs:25:5
    |
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
@@ -86,15 +88,16 @@ LL |     i32::try_from(1usize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:22:5
+  --> $DIR/cast_size.rs:25:5
    |
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
    |
    = note: `-D clippy::cast-possible-wrap` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]`
 
 error: casting `i64` to `isize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:24:5
+  --> $DIR/cast_size.rs:26:5
    |
 LL |     1i64 as isize;
    |     ^^^^^^^^^^^^^
@@ -106,7 +109,7 @@ LL |     isize::try_from(1i64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:25:5
+  --> $DIR/cast_size.rs:27:5
    |
 LL |     1i64 as usize;
    |     ^^^^^^^^^^^^^
@@ -118,7 +121,7 @@ LL |     usize::try_from(1i64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:26:5
+  --> $DIR/cast_size.rs:28:5
    |
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
@@ -130,13 +133,13 @@ LL |     isize::try_from(1u64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:26:5
+  --> $DIR/cast_size.rs:28:5
    |
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
 
 error: casting `u64` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:27:5
+  --> $DIR/cast_size.rs:29:5
    |
 LL |     1u64 as usize;
    |     ^^^^^^^^^^^^^
@@ -148,24 +151,31 @@ LL |     usize::try_from(1u64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size_32bit.rs:28:5
+  --> $DIR/cast_size.rs:30:5
    |
 LL |     1u32 as isize;
    |     ^^^^^^^^^^^^^
 
 error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> $DIR/cast_size_32bit.rs:33:5
+  --> $DIR/cast_size.rs:35:5
    |
 LL |     999_999_999 as f32;
    |     ^^^^^^^^^^^^^^^^^^
 
-error: casting integer literal to `f64` is unnecessary
-  --> $DIR/cast_size_32bit.rs:34:5
+error: casting `usize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`usize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
+  --> $DIR/cast_size.rs:36:5
    |
-LL |     3_999_999_999usize as f64;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `3_999_999_999_f64`
+LL |     9_999_999_999_999_999usize as f64;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: literal out of range for `usize`
+  --> $DIR/cast_size.rs:36:5
    |
-   = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
+LL |     9_999_999_999_999_999usize as f64;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9_999_999_999_999_999usize` does not fit into the type `usize` whose range is `0..=4294967295`
+   = note: `#[deny(overflowing_literals)]` on by default
 
-error: aborting due to 18 previous errors
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.64bit.stderr
similarity index 94%
rename from tests/ui/cast_size.stderr
rename to tests/ui/cast_size.64bit.stderr
index bc9224be644..7fae92b1250 100644
--- a/tests/ui/cast_size.stderr
+++ b/tests/ui/cast_size.64bit.stderr
@@ -1,5 +1,5 @@
 error: casting `isize` to `i8` may truncate the value
-  --> $DIR/cast_size.rs:12:5
+  --> $DIR/cast_size.rs:15:5
    |
 LL |     1isize as i8;
    |     ^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL |     i8::try_from(1isize);
    |     ~~~~~~~~~~~~~~~~~~~~
 
 error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
-  --> $DIR/cast_size.rs:16:5
+  --> $DIR/cast_size.rs:18:5
    |
 LL |     x0 as f64;
    |     ^^^^^^^^^
@@ -28,19 +28,19 @@ LL |     x1 as f64;
    |     ^^^^^^^^^
 
 error: casting `isize` to `f32` causes a loss of precision (`isize` is 32 or 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> $DIR/cast_size.rs:21:5
+  --> $DIR/cast_size.rs:20:5
    |
 LL |     x0 as f32;
    |     ^^^^^^^^^
 
 error: casting `usize` to `f32` causes a loss of precision (`usize` is 32 or 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> $DIR/cast_size.rs:23:5
+  --> $DIR/cast_size.rs:21:5
    |
 LL |     x1 as f32;
    |     ^^^^^^^^^
 
 error: casting `isize` to `i32` may truncate the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size.rs:25:5
+  --> $DIR/cast_size.rs:22:5
    |
 LL |     1isize as i32;
    |     ^^^^^^^^^^^^^
@@ -52,7 +52,7 @@ LL |     i32::try_from(1isize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size.rs:27:5
+  --> $DIR/cast_size.rs:23:5
    |
 LL |     1isize as u32;
    |     ^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     u32::try_from(1isize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size.rs:29:5
+  --> $DIR/cast_size.rs:24:5
    |
 LL |     1usize as u32;
    |     ^^^^^^^^^^^^^
@@ -76,7 +76,7 @@ LL |     u32::try_from(1usize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size.rs:31:5
+  --> $DIR/cast_size.rs:25:5
    |
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     i32::try_from(1usize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size.rs:31:5
+  --> $DIR/cast_size.rs:25:5
    |
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
@@ -97,7 +97,7 @@ LL |     1usize as i32;
    = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]`
 
 error: casting `i64` to `isize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size.rs:36:5
+  --> $DIR/cast_size.rs:26:5
    |
 LL |     1i64 as isize;
    |     ^^^^^^^^^^^^^
@@ -109,7 +109,7 @@ LL |     isize::try_from(1i64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size.rs:38:5
+  --> $DIR/cast_size.rs:27:5
    |
 LL |     1i64 as usize;
    |     ^^^^^^^^^^^^^
@@ -121,7 +121,7 @@ LL |     usize::try_from(1i64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size.rs:40:5
+  --> $DIR/cast_size.rs:28:5
    |
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
@@ -133,13 +133,13 @@ LL |     isize::try_from(1u64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
-  --> $DIR/cast_size.rs:40:5
+  --> $DIR/cast_size.rs:28:5
    |
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
 
 error: casting `u64` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size.rs:43:5
+  --> $DIR/cast_size.rs:29:5
    |
 LL |     1u64 as usize;
    |     ^^^^^^^^^^^^^
@@ -151,19 +151,19 @@ LL |     usize::try_from(1u64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
-  --> $DIR/cast_size.rs:45:5
+  --> $DIR/cast_size.rs:30:5
    |
 LL |     1u32 as isize;
    |     ^^^^^^^^^^^^^
 
 error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> $DIR/cast_size.rs:51:5
+  --> $DIR/cast_size.rs:35:5
    |
 LL |     999_999_999 as f32;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: casting `usize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`usize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
-  --> $DIR/cast_size.rs:53:5
+  --> $DIR/cast_size.rs:36:5
    |
 LL |     9_999_999_999_999_999usize as f64;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs
index 95626b20b27..d063a70ccdf 100644
--- a/tests/ui/cast_size.rs
+++ b/tests/ui/cast_size.rs
@@ -1,56 +1,37 @@
-//@ignore-32bit
-#[warn(
+//@stderr-per-bitwidth
+//@no-rustfix
+
+#![warn(
     clippy::cast_precision_loss,
     clippy::cast_possible_truncation,
     clippy::cast_sign_loss,
     clippy::cast_possible_wrap,
     clippy::cast_lossless
 )]
-#[allow(clippy::no_effect, clippy::unnecessary_operation)]
+#![allow(clippy::no_effect, clippy::unnecessary_operation)]
+
 fn main() {
     // Casting from *size
     1isize as i8;
-    //~^ ERROR: casting `isize` to `i8` may truncate the value
     let x0 = 1isize;
     let x1 = 1usize;
     x0 as f64;
-    //~^ ERROR: casting `isize` to `f64` causes a loss of precision on targets with 64-bit
-    //~| NOTE: `-D clippy::cast-precision-loss` implied by `-D warnings`
     x1 as f64;
-    //~^ ERROR: casting `usize` to `f64` causes a loss of precision on targets with 64-bit
     x0 as f32;
-    //~^ ERROR: casting `isize` to `f32` causes a loss of precision (`isize` is 32 or 64 b
     x1 as f32;
-    //~^ ERROR: casting `usize` to `f32` causes a loss of precision (`usize` is 32 or 64 b
     1isize as i32;
-    //~^ ERROR: casting `isize` to `i32` may truncate the value on targets with 64-bit wid
     1isize as u32;
-    //~^ ERROR: casting `isize` to `u32` may truncate the value on targets with 64-bit wid
     1usize as u32;
-    //~^ ERROR: casting `usize` to `u32` may truncate the value on targets with 64-bit wid
     1usize as i32;
-    //~^ ERROR: casting `usize` to `i32` may truncate the value on targets with 64-bit wid
-    //~| ERROR: casting `usize` to `i32` may wrap around the value on targets with 32-bit
-    //~| NOTE: `-D clippy::cast-possible-wrap` implied by `-D warnings`
-    // Casting to *size
     1i64 as isize;
-    //~^ ERROR: casting `i64` to `isize` may truncate the value on targets with 32-bit wid
     1i64 as usize;
-    //~^ ERROR: casting `i64` to `usize` may truncate the value on targets with 32-bit wid
     1u64 as isize;
-    //~^ ERROR: casting `u64` to `isize` may truncate the value on targets with 32-bit wid
-    //~| ERROR: casting `u64` to `isize` may wrap around the value on targets with 64-bit
     1u64 as usize;
-    //~^ ERROR: casting `u64` to `usize` may truncate the value on targets with 32-bit wid
     1u32 as isize;
-    //~^ ERROR: casting `u32` to `isize` may wrap around the value on targets with 32-bit
     1u32 as usize; // Should not trigger any lint
     1i32 as isize; // Neither should this
     1i32 as usize;
     // Big integer literal to float
     999_999_999 as f32;
-    //~^ ERROR: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide,
     9_999_999_999_999_999usize as f64;
-    //~^ ERROR: casting `usize` to `f64` causes a loss of precision on targets with 64-bit
 }
-//@no-rustfix
diff --git a/tests/ui/cast_size_32bit.rs b/tests/ui/cast_size_32bit.rs
deleted file mode 100644
index 5a06e34bdb8..00000000000
--- a/tests/ui/cast_size_32bit.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-//@ignore-64bit
-#[warn(
-    clippy::cast_precision_loss,
-    clippy::cast_possible_truncation,
-    clippy::cast_sign_loss,
-    clippy::cast_possible_wrap,
-    clippy::cast_lossless
-)]
-#[allow(clippy::no_effect, clippy::unnecessary_operation)]
-fn main() {
-    // Casting from *size
-    1isize as i8;
-    //~^ ERROR: casting `isize` to `i8` may truncate the value
-    let x0 = 1isize;
-    let x1 = 1usize;
-    x0 as f64;
-    //~^ ERROR: casting `isize` to `f64` causes a loss of precision on targets with 64-bit
-    //~| NOTE: `-D clippy::cast-precision-loss` implied by `-D warnings`
-    x1 as f64;
-    //~^ ERROR: casting `usize` to `f64` causes a loss of precision on targets with 64-bit
-    x0 as f32;
-    //~^ ERROR: casting `isize` to `f32` causes a loss of precision (`isize` is 32 or 64 b
-    x1 as f32;
-    //~^ ERROR: casting `usize` to `f32` causes a loss of precision (`usize` is 32 or 64 b
-    1isize as i32;
-    //~^ ERROR: casting `isize` to `i32` may truncate the value on targets with 64-bit wid
-    1isize as u32;
-    //~^ ERROR: casting `isize` to `u32` may truncate the value on targets with 64-bit wid
-    1usize as u32;
-    //~^ ERROR: casting `usize` to `u32` may truncate the value on targets with 64-bit wid
-    1usize as i32;
-    //~^ ERROR: casting `usize` to `i32` may truncate the value on targets with 64-bit wid
-    //~| ERROR: casting `usize` to `i32` may wrap around the value on targets with 32-bit
-    //~| NOTE: `-D clippy::cast-possible-wrap` implied by `-D warnings`
-    // Casting to *size
-    1i64 as isize;
-    //~^ ERROR: casting `i64` to `isize` may truncate the value on targets with 32-bit wid
-    1i64 as usize;
-    //~^ ERROR: casting `i64` to `usize` may truncate the value on targets with 32-bit wid
-    1u64 as isize;
-    //~^ ERROR: casting `u64` to `isize` may truncate the value on targets with 32-bit wid
-    //~| ERROR: casting `u64` to `isize` may wrap around the value on targets with 64-bit
-    1u64 as usize;
-    //~^ ERROR: casting `u64` to `usize` may truncate the value on targets with 32-bit wid
-    1u32 as isize;
-    //~^ ERROR: casting `u32` to `isize` may wrap around the value on targets with 32-bit
-    1u32 as usize; // Should not trigger any lint
-    1i32 as isize; // Neither should this
-    1i32 as usize;
-    // Big integer literal to float
-    999_999_999 as f32;
-    //~^ ERROR: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide,
-    3_999_999_999usize as f64;
-    //~^ ERROR: casting integer literal to `f64` is unnecessary
-    //~| NOTE: `-D clippy::unnecessary-cast` implied by `-D warnings`
-}
diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs
index e82e7bcb06c..02f80cc52ac 100644
--- a/tests/ui/checked_unwrap/simple_conditionals.rs
+++ b/tests/ui/checked_unwrap/simple_conditionals.rs
@@ -128,6 +128,57 @@ fn main() {
     assert!(x.is_ok(), "{:?}", x.unwrap_err());
 }
 
+fn issue11371() {
+    let option = Some(());
+
+    if option.is_some() {
+        option.as_ref().unwrap();
+        //~^ ERROR: called `unwrap` on `option` after checking its variant with `is_some`
+    } else {
+        option.as_ref().unwrap();
+        //~^ ERROR: this call to `unwrap()` will always panic
+    }
+
+    let result = Ok::<(), ()>(());
+
+    if result.is_ok() {
+        result.as_ref().unwrap();
+        //~^ ERROR: called `unwrap` on `result` after checking its variant with `is_ok`
+    } else {
+        result.as_ref().unwrap();
+        //~^ ERROR: this call to `unwrap()` will always panic
+    }
+
+    let mut option = Some(());
+    if option.is_some() {
+        option.as_mut().unwrap();
+        //~^ ERROR: called `unwrap` on `option` after checking its variant with `is_some`
+    } else {
+        option.as_mut().unwrap();
+        //~^ ERROR: this call to `unwrap()` will always panic
+    }
+
+    let mut result = Ok::<(), ()>(());
+    if result.is_ok() {
+        result.as_mut().unwrap();
+        //~^ ERROR: called `unwrap` on `result` after checking its variant with `is_ok`
+    } else {
+        result.as_mut().unwrap();
+        //~^ ERROR: this call to `unwrap()` will always panic
+    }
+
+    // This should not lint. Statics are, at the time of writing, not linted on anyway,
+    // but if at some point they are supported by this lint, it should correctly see that
+    // `X` is being mutated and not suggest `if let Some(..) = X {}`
+    static mut X: Option<i32> = Some(123);
+    unsafe {
+        if X.is_some() {
+            X = None;
+            X.unwrap();
+        }
+    }
+}
+
 fn check_expect() {
     let x = Some(());
     if x.is_some() {
diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr
index ed603581ecd..a5afbba7317 100644
--- a/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -168,5 +168,73 @@ LL |     if x.is_err() {
 LL |         x.unwrap_err();
    |         ^^^^^^^^^^^^^^
 
-error: aborting due to 17 previous errors
+error: called `unwrap` on `option` after checking its variant with `is_some`
+  --> $DIR/simple_conditionals.rs:135:9
+   |
+LL |     if option.is_some() {
+   |     ------------------- help: try: `if let Some(..) = &option`
+LL |         option.as_ref().unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this call to `unwrap()` will always panic
+  --> $DIR/simple_conditionals.rs:138:9
+   |
+LL |     if option.is_some() {
+   |        ---------------- because of this check
+...
+LL |         option.as_ref().unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: called `unwrap` on `result` after checking its variant with `is_ok`
+  --> $DIR/simple_conditionals.rs:145:9
+   |
+LL |     if result.is_ok() {
+   |     ----------------- help: try: `if let Ok(..) = &result`
+LL |         result.as_ref().unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this call to `unwrap()` will always panic
+  --> $DIR/simple_conditionals.rs:148:9
+   |
+LL |     if result.is_ok() {
+   |        -------------- because of this check
+...
+LL |         result.as_ref().unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: called `unwrap` on `option` after checking its variant with `is_some`
+  --> $DIR/simple_conditionals.rs:154:9
+   |
+LL |     if option.is_some() {
+   |     ------------------- help: try: `if let Some(..) = &mut option`
+LL |         option.as_mut().unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this call to `unwrap()` will always panic
+  --> $DIR/simple_conditionals.rs:157:9
+   |
+LL |     if option.is_some() {
+   |        ---------------- because of this check
+...
+LL |         option.as_mut().unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: called `unwrap` on `result` after checking its variant with `is_ok`
+  --> $DIR/simple_conditionals.rs:163:9
+   |
+LL |     if result.is_ok() {
+   |     ----------------- help: try: `if let Ok(..) = &mut result`
+LL |         result.as_mut().unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this call to `unwrap()` will always panic
+  --> $DIR/simple_conditionals.rs:166:9
+   |
+LL |     if result.is_ok() {
+   |        -------------- because of this check
+...
+LL |         result.as_mut().unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 25 previous errors
 
diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs
index b7c186bef77..2d03544ad8b 100644
--- a/tests/ui/clone_on_copy_impl.rs
+++ b/tests/ui/clone_on_copy_impl.rs
@@ -1,4 +1,4 @@
-#![allow(clippy::incorrect_clone_impl_on_copy_type)]
+#![allow(clippy::non_canonical_clone_impl)]
 
 use std::fmt;
 use std::marker::PhantomData;
diff --git a/tests/ui/crashes/ice-11337.rs b/tests/ui/crashes/ice-11337.rs
new file mode 100644
index 00000000000..0bed4035f6b
--- /dev/null
+++ b/tests/ui/crashes/ice-11337.rs
@@ -0,0 +1,9 @@
+#![feature(trait_alias)]
+
+trait Confusing<F> = Fn(i32) where F: Fn(u32);
+
+fn alias<T: Confusing<F>, F>(_: T, _: F) {}
+
+fn main() {
+    alias(|_| {}, |_| {});
+}
diff --git a/tests/ui/crashes/ice-11422.fixed b/tests/ui/crashes/ice-11422.fixed
new file mode 100644
index 00000000000..ca5721cbb2b
--- /dev/null
+++ b/tests/ui/crashes/ice-11422.fixed
@@ -0,0 +1,25 @@
+#![warn(clippy::implied_bounds_in_impls)]
+
+use std::fmt::Debug;
+use std::ops::*;
+
+fn gen() -> impl PartialOrd + Debug {}
+
+struct Bar {}
+trait Foo<T = Self> {}
+trait FooNested<T = Option<Self>> {}
+impl Foo for Bar {}
+impl FooNested for Bar {}
+
+fn foo() -> impl Foo + FooNested {
+    Bar {}
+}
+
+fn test_impl_ops() -> impl Add + Sub + Mul + Div {
+    1
+}
+fn test_impl_assign_ops() -> impl AddAssign + SubAssign + MulAssign + DivAssign {
+    1
+}
+
+fn main() {}
diff --git a/tests/ui/crashes/ice-11422.rs b/tests/ui/crashes/ice-11422.rs
new file mode 100644
index 00000000000..355ec2480bb
--- /dev/null
+++ b/tests/ui/crashes/ice-11422.rs
@@ -0,0 +1,25 @@
+#![warn(clippy::implied_bounds_in_impls)]
+
+use std::fmt::Debug;
+use std::ops::*;
+
+fn gen() -> impl PartialOrd + PartialEq + Debug {}
+
+struct Bar {}
+trait Foo<T = Self> {}
+trait FooNested<T = Option<Self>> {}
+impl Foo for Bar {}
+impl FooNested for Bar {}
+
+fn foo() -> impl Foo + FooNested {
+    Bar {}
+}
+
+fn test_impl_ops() -> impl Add + Sub + Mul + Div {
+    1
+}
+fn test_impl_assign_ops() -> impl AddAssign + SubAssign + MulAssign + DivAssign {
+    1
+}
+
+fn main() {}
diff --git a/tests/ui/crashes/ice-11422.stderr b/tests/ui/crashes/ice-11422.stderr
new file mode 100644
index 00000000000..fb80b5b147f
--- /dev/null
+++ b/tests/ui/crashes/ice-11422.stderr
@@ -0,0 +1,16 @@
+error: this bound is already specified as the supertrait of `PartialOrd`
+  --> $DIR/ice-11422.rs:6:31
+   |
+LL | fn gen() -> impl PartialOrd + PartialEq + Debug {}
+   |                               ^^^^^^^^^
+   |
+   = note: `-D clippy::implied-bounds-in-impls` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::implied_bounds_in_impls)]`
+help: try removing this bound
+   |
+LL - fn gen() -> impl PartialOrd + PartialEq + Debug {}
+LL + fn gen() -> impl PartialOrd + Debug {}
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/crashes/ice-360.rs b/tests/ui/crashes/ice-360.rs
index 28589e1efed..0d10932b098 100644
--- a/tests/ui/crashes/ice-360.rs
+++ b/tests/ui/crashes/ice-360.rs
@@ -3,7 +3,8 @@ fn main() {}
 fn no_panic<T>(slice: &[T]) {
     let mut iter = slice.iter();
     loop {
-        //~^ ERROR: this loop could be written as a `while let` loop
+        //~^ ERROR: this loop never actually loops
+        //~| ERROR: this loop could be written as a `while let` loop
         //~| NOTE: `-D clippy::while-let-loop` implied by `-D warnings`
         let _ = match iter.next() {
             Some(ele) => ele,
diff --git a/tests/ui/crashes/ice-360.stderr b/tests/ui/crashes/ice-360.stderr
index dd016355b53..a84697a9f29 100644
--- a/tests/ui/crashes/ice-360.stderr
+++ b/tests/ui/crashes/ice-360.stderr
@@ -1,10 +1,24 @@
+error: this loop never actually loops
+  --> $DIR/ice-360.rs:5:5
+   |
+LL | /     loop {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     }
+   | |_____^
+   |
+   = note: `#[deny(clippy::never_loop)]` on by default
+
 error: this loop could be written as a `while let` loop
   --> $DIR/ice-360.rs:5:5
    |
 LL | /     loop {
 LL | |
 LL | |
-LL | |         let _ = match iter.next() {
+LL | |
 ...  |
 LL | |
 LL | |     }
@@ -14,7 +28,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::while_let_loop)]`
 
 error: empty `loop {}` wastes CPU cycles
-  --> $DIR/ice-360.rs:12:9
+  --> $DIR/ice-360.rs:13:9
    |
 LL |         loop {}
    |         ^^^^^^^
@@ -23,5 +37,5 @@ LL |         loop {}
    = note: `-D clippy::empty-loop` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::empty_loop)]`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed
index 6cc202414f5..68c5a5c5ca4 100644
--- a/tests/ui/derivable_impls.fixed
+++ b/tests/ui/derivable_impls.fixed
@@ -287,4 +287,17 @@ mod issue10158 {
     }
 }
 
+mod issue11368 {
+    pub struct A {
+        a: u32,
+    }
+
+    impl Default for A {
+        #[track_caller]
+        fn default() -> Self {
+            Self { a: 0 }
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs
index 0aa9acd752d..21d73ba8b77 100644
--- a/tests/ui/derivable_impls.rs
+++ b/tests/ui/derivable_impls.rs
@@ -323,4 +323,17 @@ mod issue10158 {
     }
 }
 
+mod issue11368 {
+    pub struct A {
+        a: u32,
+    }
+
+    impl Default for A {
+        #[track_caller]
+        fn default() -> Self {
+            Self { a: 0 }
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs
index 310c701765b..20ac8a6e6be 100644
--- a/tests/ui/derive.rs
+++ b/tests/ui/derive.rs
@@ -1,8 +1,4 @@
-#![allow(
-    clippy::incorrect_clone_impl_on_copy_type,
-    clippy::incorrect_partial_ord_impl_on_ord_type,
-    dead_code
-)]
+#![allow(clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, dead_code)]
 #![warn(clippy::expl_impl_clone_on_copy)]
 
 
diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr
index e9b2ee34760..88942d95432 100644
--- a/tests/ui/derive.stderr
+++ b/tests/ui/derive.stderr
@@ -1,5 +1,5 @@
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:12:1
+  --> $DIR/derive.rs:8:1
    |
 LL | / impl Clone for Qux {
 LL | |
@@ -10,7 +10,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:12:1
+  --> $DIR/derive.rs:8:1
    |
 LL | / impl Clone for Qux {
 LL | |
@@ -23,7 +23,7 @@ LL | | }
    = help: to override `-D warnings` add `#[allow(clippy::expl_impl_clone_on_copy)]`
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:37:1
+  --> $DIR/derive.rs:33:1
    |
 LL | / impl<'a> Clone for Lt<'a> {
 LL | |
@@ -34,7 +34,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:37:1
+  --> $DIR/derive.rs:33:1
    |
 LL | / impl<'a> Clone for Lt<'a> {
 LL | |
@@ -45,7 +45,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:49:1
+  --> $DIR/derive.rs:45:1
    |
 LL | / impl Clone for BigArray {
 LL | |
@@ -56,7 +56,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:49:1
+  --> $DIR/derive.rs:45:1
    |
 LL | / impl Clone for BigArray {
 LL | |
@@ -67,7 +67,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:61:1
+  --> $DIR/derive.rs:57:1
    |
 LL | / impl Clone for FnPtr {
 LL | |
@@ -78,7 +78,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:61:1
+  --> $DIR/derive.rs:57:1
    |
 LL | / impl Clone for FnPtr {
 LL | |
@@ -89,7 +89,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:82:1
+  --> $DIR/derive.rs:78:1
    |
 LL | / impl<T: Clone> Clone for Generic2<T> {
 LL | |
@@ -100,7 +100,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:82:1
+  --> $DIR/derive.rs:78:1
    |
 LL | / impl<T: Clone> Clone for Generic2<T> {
 LL | |
diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs
index 2c19942d420..1c7e6d1c202 100644
--- a/tests/ui/derive_ord_xor_partial_ord.rs
+++ b/tests/ui/derive_ord_xor_partial_ord.rs
@@ -1,6 +1,6 @@
 #![warn(clippy::derive_ord_xor_partial_ord)]
 #![allow(clippy::unnecessary_wraps)]
-#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)]
+#![allow(clippy::non_canonical_partial_ord_impl)]
 
 use std::cmp::Ordering;
 
diff --git a/tests/ui/empty_loop.rs b/tests/ui/empty_loop.rs
index 54e8fb4907c..be347563135 100644
--- a/tests/ui/empty_loop.rs
+++ b/tests/ui/empty_loop.rs
@@ -7,10 +7,12 @@ use proc_macros::{external, inline_macros};
 
 fn should_trigger() {
     loop {}
+    #[allow(clippy::never_loop)]
     loop {
         loop {}
     }
 
+    #[allow(clippy::never_loop)]
     'outer: loop {
         'inner: loop {}
     }
@@ -18,6 +20,7 @@ fn should_trigger() {
 
 #[inline_macros]
 fn should_not_trigger() {
+    #[allow(clippy::never_loop)]
     loop {
         panic!("This is fine")
     }
diff --git a/tests/ui/empty_loop.stderr b/tests/ui/empty_loop.stderr
index 84d7d61c7da..113556f673c 100644
--- a/tests/ui/empty_loop.stderr
+++ b/tests/ui/empty_loop.stderr
@@ -9,7 +9,7 @@ LL |     loop {}
    = help: to override `-D warnings` add `#[allow(clippy::empty_loop)]`
 
 error: empty `loop {}` wastes CPU cycles
-  --> $DIR/empty_loop.rs:11:9
+  --> $DIR/empty_loop.rs:12:9
    |
 LL |         loop {}
    |         ^^^^^^^
@@ -17,7 +17,7 @@ LL |         loop {}
    = help: you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body
 
 error: empty `loop {}` wastes CPU cycles
-  --> $DIR/empty_loop.rs:15:9
+  --> $DIR/empty_loop.rs:17:9
    |
 LL |         'inner: loop {}
    |         ^^^^^^^^^^^^^^^
diff --git a/tests/ui/enum_clike_unportable_variant.rs b/tests/ui/enum_clike_unportable_variant.rs
index 964e5634ddb..c50404c5047 100644
--- a/tests/ui/enum_clike_unportable_variant.rs
+++ b/tests/ui/enum_clike_unportable_variant.rs
@@ -1,4 +1,4 @@
-//@ignore-target-x86
+//@ignore-32bit
 
 #![warn(clippy::enum_clike_unportable_variant)]
 #![allow(unused, non_upper_case_globals)]
diff --git a/tests/ui/enum_clike_unportable_variant.stderr b/tests/ui/enum_clike_unportable_variant.stderr
index 5935eea5e03..93ad4daa97f 100644
--- a/tests/ui/enum_clike_unportable_variant.stderr
+++ b/tests/ui/enum_clike_unportable_variant.stderr
@@ -5,51 +5,52 @@ LL |     X = 0x1_0000_0000,
    |     ^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::enum-clike-unportable-variant` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::enum_clike_unportable_variant)]`
 
 error: C-like enum variant discriminant is not portable to 32-bit targets
-  --> $DIR/enum_clike_unportable_variant.rs:15:5
+  --> $DIR/enum_clike_unportable_variant.rs:17:5
    |
 LL |     X = 0x1_0000_0000,
    |     ^^^^^^^^^^^^^^^^^
 
 error: C-like enum variant discriminant is not portable to 32-bit targets
-  --> $DIR/enum_clike_unportable_variant.rs:18:5
+  --> $DIR/enum_clike_unportable_variant.rs:21:5
    |
 LL |     A = 0xFFFF_FFFF,
    |     ^^^^^^^^^^^^^^^
 
 error: C-like enum variant discriminant is not portable to 32-bit targets
-  --> $DIR/enum_clike_unportable_variant.rs:25:5
+  --> $DIR/enum_clike_unportable_variant.rs:29:5
    |
 LL |     Z = 0xFFFF_FFFF,
    |     ^^^^^^^^^^^^^^^
 
 error: C-like enum variant discriminant is not portable to 32-bit targets
-  --> $DIR/enum_clike_unportable_variant.rs:26:5
+  --> $DIR/enum_clike_unportable_variant.rs:31:5
    |
 LL |     A = 0x1_0000_0000,
    |     ^^^^^^^^^^^^^^^^^
 
 error: C-like enum variant discriminant is not portable to 32-bit targets
-  --> $DIR/enum_clike_unportable_variant.rs:28:5
+  --> $DIR/enum_clike_unportable_variant.rs:34:5
    |
 LL |     C = (i32::MIN as isize) - 1,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: C-like enum variant discriminant is not portable to 32-bit targets
-  --> $DIR/enum_clike_unportable_variant.rs:34:5
+  --> $DIR/enum_clike_unportable_variant.rs:41:5
    |
 LL |     Z = 0xFFFF_FFFF,
    |     ^^^^^^^^^^^^^^^
 
 error: C-like enum variant discriminant is not portable to 32-bit targets
-  --> $DIR/enum_clike_unportable_variant.rs:35:5
+  --> $DIR/enum_clike_unportable_variant.rs:43:5
    |
 LL |     A = 0x1_0000_0000,
    |     ^^^^^^^^^^^^^^^^^
 
 error: C-like enum variant discriminant is not portable to 32-bit targets
-  --> $DIR/enum_clike_unportable_variant.rs:40:5
+  --> $DIR/enum_clike_unportable_variant.rs:49:5
    |
 LL |     X = <usize as Trait>::Number,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed
index 86bee11eb87..12158d0d12a 100644
--- a/tests/ui/explicit_auto_deref.fixed
+++ b/tests/ui/explicit_auto_deref.fixed
@@ -205,7 +205,7 @@ fn main() {
         }
     }
 
-    f_str(&&ref_str); // `needless_borrow` will suggest removing both references
+    f_str(&ref_str); // `needless_borrow` will suggest removing both references
     f_str(&ref_str); // `needless_borrow` will suggest removing only one reference
 
     let x = &&40;
@@ -293,4 +293,32 @@ fn main() {
     fn return_dyn_assoc<'a>(x: &'a &'a u32) -> &'a <&'a u32 as WithAssoc>::Assoc {
         *x
     }
+
+    // Issue #11366
+    let _: &mut u32 = match &mut Some(&mut 0u32) {
+        Some(x) => x,
+        None => panic!(),
+    };
+
+    // Issue #11474
+    pub struct Variant {
+        pub anonymous: Variant0,
+    }
+
+    pub union Variant0 {
+        pub anonymous: std::mem::ManuallyDrop<Variant00>,
+    }
+
+    pub struct Variant00 {
+        pub anonymous: Variant000,
+    }
+
+    pub union Variant000 {
+        pub val: i32,
+    }
+
+    unsafe {
+        let mut p = core::mem::zeroed::<Variant>();
+        (*p.anonymous.anonymous).anonymous.val = 1;
+    }
 }
diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs
index 7a505bdf558..dec021c1834 100644
--- a/tests/ui/explicit_auto_deref.rs
+++ b/tests/ui/explicit_auto_deref.rs
@@ -293,4 +293,32 @@ fn main() {
     fn return_dyn_assoc<'a>(x: &'a &'a u32) -> &'a <&'a u32 as WithAssoc>::Assoc {
         *x
     }
+
+    // Issue #11366
+    let _: &mut u32 = match &mut Some(&mut 0u32) {
+        Some(x) => &mut *x,
+        None => panic!(),
+    };
+
+    // Issue #11474
+    pub struct Variant {
+        pub anonymous: Variant0,
+    }
+
+    pub union Variant0 {
+        pub anonymous: std::mem::ManuallyDrop<Variant00>,
+    }
+
+    pub struct Variant00 {
+        pub anonymous: Variant000,
+    }
+
+    pub union Variant000 {
+        pub val: i32,
+    }
+
+    unsafe {
+        let mut p = core::mem::zeroed::<Variant>();
+        (*p.anonymous.anonymous).anonymous.val = 1;
+    }
 }
diff --git a/tests/ui/explicit_auto_deref.stderr b/tests/ui/explicit_auto_deref.stderr
index bea014d8ad5..3d2a7b0d9f4 100644
--- a/tests/ui/explicit_auto_deref.stderr
+++ b/tests/ui/explicit_auto_deref.stderr
@@ -194,10 +194,10 @@ LL |     let _ = f_str(**ref_ref_str);
    |                   ^^^^^^^^^^^^^ help: try: `ref_ref_str`
 
 error: deref which would be done by auto-deref
-  --> $DIR/explicit_auto_deref.rs:208:13
+  --> $DIR/explicit_auto_deref.rs:208:12
    |
 LL |     f_str(&&*ref_str); // `needless_borrow` will suggest removing both references
-   |             ^^^^^^^^ help: try: `ref_str`
+   |            ^^^^^^^^^ help: try: `ref_str`
 
 error: deref which would be done by auto-deref
   --> $DIR/explicit_auto_deref.rs:209:12
@@ -235,5 +235,11 @@ error: deref which would be done by auto-deref
 LL |         *x
    |         ^^ help: try: `x`
 
-error: aborting due to 39 previous errors
+error: deref which would be done by auto-deref
+  --> $DIR/explicit_auto_deref.rs:299:20
+   |
+LL |         Some(x) => &mut *x,
+   |                    ^^^^^^^ help: try: `x`
+
+error: aborting due to 40 previous errors
 
diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed
index 57292114e38..f08397defa5 100644
--- a/tests/ui/explicit_iter_loop.fixed
+++ b/tests/ui/explicit_iter_loop.fixed
@@ -4,6 +4,7 @@
     clippy::similar_names,
     clippy::needless_borrow,
     clippy::deref_addrof,
+    clippy::unnecessary_mut_passed,
     dead_code
 )]
 
@@ -20,15 +21,15 @@ fn main() {
     for _ in rvec {}
 
     let rmvec = &mut vec;
-    for _ in &*rmvec {}
-    for _ in &mut *rmvec {}
+    for _ in rmvec.iter() {}
+    for _ in rmvec.iter_mut() {}
 
     for _ in &vec {} // these are fine
     for _ in &mut vec {} // these are fine
 
     for _ in &[1, 2, 3] {}
 
-    for _ in &*(&mut [1, 2, 3]) {}
+    for _ in (&mut [1, 2, 3]).iter() {}
 
     for _ in &[0; 32] {}
     for _ in &[0; 33] {}
diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs
index 66280c23843..2ee6825d445 100644
--- a/tests/ui/explicit_iter_loop.rs
+++ b/tests/ui/explicit_iter_loop.rs
@@ -4,6 +4,7 @@
     clippy::similar_names,
     clippy::needless_borrow,
     clippy::deref_addrof,
+    clippy::unnecessary_mut_passed,
     dead_code
 )]
 
diff --git a/tests/ui/explicit_iter_loop.stderr b/tests/ui/explicit_iter_loop.stderr
index af46d74e989..725d9b63cf8 100644
--- a/tests/ui/explicit_iter_loop.stderr
+++ b/tests/ui/explicit_iter_loop.stderr
@@ -1,5 +1,5 @@
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:16:14
+  --> $DIR/explicit_iter_loop.rs:17:14
    |
 LL |     for _ in vec.iter() {}
    |              ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
@@ -11,133 +11,106 @@ LL | #![deny(clippy::explicit_iter_loop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:17:14
+  --> $DIR/explicit_iter_loop.rs:18:14
    |
 LL |     for _ in vec.iter_mut() {}
    |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:20:14
+  --> $DIR/explicit_iter_loop.rs:21:14
    |
 LL |     for _ in rvec.iter() {}
    |              ^^^^^^^^^^^ help: to write this more concisely, try: `rvec`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:23:14
-   |
-LL |     for _ in rmvec.iter() {}
-   |              ^^^^^^^^^^^^ help: to write this more concisely, try: `&*rmvec`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:24:14
-   |
-LL |     for _ in rmvec.iter_mut() {}
-   |              ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *rmvec`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:29:14
+  --> $DIR/explicit_iter_loop.rs:30:14
    |
 LL |     for _ in [1, 2, 3].iter() {}
    |              ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:31:14
-   |
-LL |     for _ in (&mut [1, 2, 3]).iter() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*(&mut [1, 2, 3])`
-
-error: the method `iter` doesn't need a mutable reference
-  --> $DIR/explicit_iter_loop.rs:31:14
-   |
-LL |     for _ in (&mut [1, 2, 3]).iter() {}
-   |              ^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::unnecessary_mut_passed)]`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:33:14
+  --> $DIR/explicit_iter_loop.rs:34:14
    |
 LL |     for _ in [0; 32].iter() {}
    |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:34:14
+  --> $DIR/explicit_iter_loop.rs:35:14
    |
 LL |     for _ in [0; 33].iter() {}
    |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:37:14
+  --> $DIR/explicit_iter_loop.rs:38:14
    |
 LL |     for _ in ll.iter() {}
    |              ^^^^^^^^^ help: to write this more concisely, try: `&ll`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:39:14
+  --> $DIR/explicit_iter_loop.rs:40:14
    |
 LL |     for _ in rll.iter() {}
    |              ^^^^^^^^^^ help: to write this more concisely, try: `rll`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:42:14
+  --> $DIR/explicit_iter_loop.rs:43:14
    |
 LL |     for _ in vd.iter() {}
    |              ^^^^^^^^^ help: to write this more concisely, try: `&vd`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:44:14
+  --> $DIR/explicit_iter_loop.rs:45:14
    |
 LL |     for _ in rvd.iter() {}
    |              ^^^^^^^^^^ help: to write this more concisely, try: `rvd`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:47:14
+  --> $DIR/explicit_iter_loop.rs:48:14
    |
 LL |     for _ in bh.iter() {}
    |              ^^^^^^^^^ help: to write this more concisely, try: `&bh`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:50:14
+  --> $DIR/explicit_iter_loop.rs:51:14
    |
 LL |     for _ in hm.iter() {}
    |              ^^^^^^^^^ help: to write this more concisely, try: `&hm`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:53:14
+  --> $DIR/explicit_iter_loop.rs:54:14
    |
 LL |     for _ in bt.iter() {}
    |              ^^^^^^^^^ help: to write this more concisely, try: `&bt`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:56:14
+  --> $DIR/explicit_iter_loop.rs:57:14
    |
 LL |     for _ in hs.iter() {}
    |              ^^^^^^^^^ help: to write this more concisely, try: `&hs`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:59:14
+  --> $DIR/explicit_iter_loop.rs:60:14
    |
 LL |     for _ in bs.iter() {}
    |              ^^^^^^^^^ help: to write this more concisely, try: `&bs`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:148:14
+  --> $DIR/explicit_iter_loop.rs:149:14
    |
 LL |     for _ in x.iter() {}
    |              ^^^^^^^^ help: to write this more concisely, try: `&x`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:149:14
+  --> $DIR/explicit_iter_loop.rs:150:14
    |
 LL |     for _ in x.iter_mut() {}
    |              ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/explicit_iter_loop.rs:152:14
+  --> $DIR/explicit_iter_loop.rs:153:14
    |
 LL |     for _ in r.iter() {}
    |              ^^^^^^^^ help: to write this more concisely, try: `r`
 
-error: aborting due to 22 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs
index a547a67430f..5057c643732 100644
--- a/tests/ui/float_cmp.rs
+++ b/tests/ui/float_cmp.rs
@@ -41,6 +41,16 @@ impl PartialEq for X {
     }
 }
 
+impl PartialEq<f32> for X {
+    fn eq(&self, o: &f32) -> bool {
+        if self.val.is_nan() {
+            o.is_nan()
+        } else {
+            self.val == *o // no error, inside "eq" fn
+        }
+    }
+}
+
 fn main() {
     ZERO == 0f32; //no error, comparison with zero is ok
     1.0f32 != f32::INFINITY; // also comparison with infinity
@@ -48,6 +58,9 @@ fn main() {
     ZERO == 0.0; //no error, comparison with zero is ok
     ZERO + ZERO != 1.0; //no error, comparison with zero is ok
 
+    let x = X { val: 1.0 };
+    x == 1.0; // no error, custom type that implement PartialOrder for float is not checked
+
     ONE == 1f32;
     ONE == 1.0 + 0.0;
     ONE + ONE == ZERO + ONE + ONE;
diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr
index cbe529954d0..217e2987917 100644
--- a/tests/ui/float_cmp.stderr
+++ b/tests/ui/float_cmp.stderr
@@ -1,5 +1,5 @@
 error: strict comparison of `f32` or `f64`
-  --> $DIR/float_cmp.rs:57:5
+  --> $DIR/float_cmp.rs:70:5
    |
 LL |     ONE as f64 != 2.0;
    |     ^^^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(ONE as f64 - 2.0).abs() > error_margin`
@@ -9,7 +9,7 @@ LL |     ONE as f64 != 2.0;
    = help: to override `-D warnings` add `#[allow(clippy::float_cmp)]`
 
 error: strict comparison of `f32` or `f64`
-  --> $DIR/float_cmp.rs:64:5
+  --> $DIR/float_cmp.rs:77:5
    |
 LL |     x == 1.0;
    |     ^^^^^^^^ help: consider comparing them within some margin of error: `(x - 1.0).abs() < error_margin`
@@ -17,7 +17,7 @@ LL |     x == 1.0;
    = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`
 
 error: strict comparison of `f32` or `f64`
-  --> $DIR/float_cmp.rs:69:5
+  --> $DIR/float_cmp.rs:82:5
    |
 LL |     twice(x) != twice(ONE as f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(twice(x) - twice(ONE as f64)).abs() > error_margin`
@@ -25,7 +25,7 @@ LL |     twice(x) != twice(ONE as f64);
    = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`
 
 error: strict comparison of `f32` or `f64`
-  --> $DIR/float_cmp.rs:91:5
+  --> $DIR/float_cmp.rs:104:5
    |
 LL |     NON_ZERO_ARRAY[i] == NON_ZERO_ARRAY[j];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(NON_ZERO_ARRAY[i] - NON_ZERO_ARRAY[j]).abs() < error_margin`
@@ -33,7 +33,7 @@ LL |     NON_ZERO_ARRAY[i] == NON_ZERO_ARRAY[j];
    = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`
 
 error: strict comparison of `f32` or `f64` arrays
-  --> $DIR/float_cmp.rs:98:5
+  --> $DIR/float_cmp.rs:111:5
    |
 LL |     a1 == a2;
    |     ^^^^^^^^
@@ -41,7 +41,7 @@ LL |     a1 == a2;
    = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`
 
 error: strict comparison of `f32` or `f64`
-  --> $DIR/float_cmp.rs:101:5
+  --> $DIR/float_cmp.rs:114:5
    |
 LL |     a1[0] == a2[0];
    |     ^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(a1[0] - a2[0]).abs() < error_margin`
diff --git a/tests/ui/fn_to_numeric_cast_32bit.stderr b/tests/ui/fn_to_numeric_cast.32bit.stderr
similarity index 70%
rename from tests/ui/fn_to_numeric_cast_32bit.stderr
rename to tests/ui/fn_to_numeric_cast.32bit.stderr
index 671347d2bcd..ea08d8c9cc1 100644
--- a/tests/ui/fn_to_numeric_cast_32bit.stderr
+++ b/tests/ui/fn_to_numeric_cast.32bit.stderr
@@ -1,141 +1,143 @@
 error: casting function pointer `foo` to `i8`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:10:13
+  --> $DIR/fn_to_numeric_cast.rs:10:13
    |
 LL |     let _ = foo as i8;
    |             ^^^^^^^^^ help: try: `foo as usize`
    |
    = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast_with_truncation)]`
 
 error: casting function pointer `foo` to `i16`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:11:13
+  --> $DIR/fn_to_numeric_cast.rs:11:13
    |
 LL |     let _ = foo as i16;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
-error: casting function pointer `foo` to `i32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:12:13
+error: casting function pointer `foo` to `i32`
+  --> $DIR/fn_to_numeric_cast.rs:12:13
    |
 LL |     let _ = foo as i32;
    |             ^^^^^^^^^^ help: try: `foo as usize`
+   |
+   = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast)]`
 
 error: casting function pointer `foo` to `i64`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:13:13
+  --> $DIR/fn_to_numeric_cast.rs:13:13
    |
 LL |     let _ = foo as i64;
    |             ^^^^^^^^^^ help: try: `foo as usize`
-   |
-   = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings`
 
 error: casting function pointer `foo` to `i128`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:14:13
+  --> $DIR/fn_to_numeric_cast.rs:14:13
    |
 LL |     let _ = foo as i128;
    |             ^^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `isize`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:15:13
+  --> $DIR/fn_to_numeric_cast.rs:15:13
    |
 LL |     let _ = foo as isize;
    |             ^^^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u8`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:17:13
+  --> $DIR/fn_to_numeric_cast.rs:17:13
    |
 LL |     let _ = foo as u8;
    |             ^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u16`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:18:13
+  --> $DIR/fn_to_numeric_cast.rs:18:13
    |
 LL |     let _ = foo as u16;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
-error: casting function pointer `foo` to `u32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:19:13
+error: casting function pointer `foo` to `u32`
+  --> $DIR/fn_to_numeric_cast.rs:19:13
    |
 LL |     let _ = foo as u32;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u64`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:20:13
+  --> $DIR/fn_to_numeric_cast.rs:20:13
    |
 LL |     let _ = foo as u64;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u128`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:21:13
+  --> $DIR/fn_to_numeric_cast.rs:21:13
    |
 LL |     let _ = foo as u128;
    |             ^^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `abc` to `i8`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:34:13
+  --> $DIR/fn_to_numeric_cast.rs:34:13
    |
 LL |     let _ = abc as i8;
    |             ^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `i16`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:35:13
+  --> $DIR/fn_to_numeric_cast.rs:35:13
    |
 LL |     let _ = abc as i16;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
-error: casting function pointer `abc` to `i32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:36:13
+error: casting function pointer `abc` to `i32`
+  --> $DIR/fn_to_numeric_cast.rs:36:13
    |
 LL |     let _ = abc as i32;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `i64`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:37:13
+  --> $DIR/fn_to_numeric_cast.rs:37:13
    |
 LL |     let _ = abc as i64;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `i128`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:38:13
+  --> $DIR/fn_to_numeric_cast.rs:38:13
    |
 LL |     let _ = abc as i128;
    |             ^^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `isize`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:39:13
+  --> $DIR/fn_to_numeric_cast.rs:39:13
    |
 LL |     let _ = abc as isize;
    |             ^^^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u8`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:41:13
+  --> $DIR/fn_to_numeric_cast.rs:41:13
    |
 LL |     let _ = abc as u8;
    |             ^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u16`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:42:13
+  --> $DIR/fn_to_numeric_cast.rs:42:13
    |
 LL |     let _ = abc as u16;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
-error: casting function pointer `abc` to `u32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:43:13
+error: casting function pointer `abc` to `u32`
+  --> $DIR/fn_to_numeric_cast.rs:43:13
    |
 LL |     let _ = abc as u32;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u64`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:44:13
+  --> $DIR/fn_to_numeric_cast.rs:44:13
    |
 LL |     let _ = abc as u64;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u128`
-  --> $DIR/fn_to_numeric_cast_32bit.rs:45:13
+  --> $DIR/fn_to_numeric_cast.rs:45:13
    |
 LL |     let _ = abc as u128;
    |             ^^^^^^^^^^^ help: try: `abc as usize`
 
-error: casting function pointer `f` to `i32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast_32bit.rs:52:5
+error: casting function pointer `f` to `i32`
+  --> $DIR/fn_to_numeric_cast.rs:52:5
    |
 LL |     f as i32
    |     ^^^^^^^^ help: try: `f as usize`
diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.64bit.stderr
similarity index 85%
rename from tests/ui/fn_to_numeric_cast.stderr
rename to tests/ui/fn_to_numeric_cast.64bit.stderr
index 53e8ac3c4b4..62f3bfa70ea 100644
--- a/tests/ui/fn_to_numeric_cast.stderr
+++ b/tests/ui/fn_to_numeric_cast.64bit.stderr
@@ -8,19 +8,19 @@ LL |     let _ = foo as i8;
    = help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast_with_truncation)]`
 
 error: casting function pointer `foo` to `i16`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:13:13
+  --> $DIR/fn_to_numeric_cast.rs:11:13
    |
 LL |     let _ = foo as i16;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `i32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:15:13
+  --> $DIR/fn_to_numeric_cast.rs:12:13
    |
 LL |     let _ = foo as i32;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `i64`
-  --> $DIR/fn_to_numeric_cast.rs:17:13
+  --> $DIR/fn_to_numeric_cast.rs:13:13
    |
 LL |     let _ = foo as i64;
    |             ^^^^^^^^^^ help: try: `foo as usize`
@@ -29,115 +29,115 @@ LL |     let _ = foo as i64;
    = help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast)]`
 
 error: casting function pointer `foo` to `i128`
-  --> $DIR/fn_to_numeric_cast.rs:20:13
+  --> $DIR/fn_to_numeric_cast.rs:14:13
    |
 LL |     let _ = foo as i128;
    |             ^^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `isize`
-  --> $DIR/fn_to_numeric_cast.rs:22:13
+  --> $DIR/fn_to_numeric_cast.rs:15:13
    |
 LL |     let _ = foo as isize;
    |             ^^^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u8`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:25:13
+  --> $DIR/fn_to_numeric_cast.rs:17:13
    |
 LL |     let _ = foo as u8;
    |             ^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u16`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:27:13
+  --> $DIR/fn_to_numeric_cast.rs:18:13
    |
 LL |     let _ = foo as u16;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:29:13
+  --> $DIR/fn_to_numeric_cast.rs:19:13
    |
 LL |     let _ = foo as u32;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u64`
-  --> $DIR/fn_to_numeric_cast.rs:31:13
+  --> $DIR/fn_to_numeric_cast.rs:20:13
    |
 LL |     let _ = foo as u64;
    |             ^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `foo` to `u128`
-  --> $DIR/fn_to_numeric_cast.rs:33:13
+  --> $DIR/fn_to_numeric_cast.rs:21:13
    |
 LL |     let _ = foo as u128;
    |             ^^^^^^^^^^^ help: try: `foo as usize`
 
 error: casting function pointer `abc` to `i8`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:47:13
+  --> $DIR/fn_to_numeric_cast.rs:34:13
    |
 LL |     let _ = abc as i8;
    |             ^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `i16`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:49:13
+  --> $DIR/fn_to_numeric_cast.rs:35:13
    |
 LL |     let _ = abc as i16;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `i32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:51:13
+  --> $DIR/fn_to_numeric_cast.rs:36:13
    |
 LL |     let _ = abc as i32;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `i64`
-  --> $DIR/fn_to_numeric_cast.rs:53:13
+  --> $DIR/fn_to_numeric_cast.rs:37:13
    |
 LL |     let _ = abc as i64;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `i128`
-  --> $DIR/fn_to_numeric_cast.rs:55:13
+  --> $DIR/fn_to_numeric_cast.rs:38:13
    |
 LL |     let _ = abc as i128;
    |             ^^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `isize`
-  --> $DIR/fn_to_numeric_cast.rs:57:13
+  --> $DIR/fn_to_numeric_cast.rs:39:13
    |
 LL |     let _ = abc as isize;
    |             ^^^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u8`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:60:13
+  --> $DIR/fn_to_numeric_cast.rs:41:13
    |
 LL |     let _ = abc as u8;
    |             ^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u16`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:62:13
+  --> $DIR/fn_to_numeric_cast.rs:42:13
    |
 LL |     let _ = abc as u16;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:64:13
+  --> $DIR/fn_to_numeric_cast.rs:43:13
    |
 LL |     let _ = abc as u32;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u64`
-  --> $DIR/fn_to_numeric_cast.rs:66:13
+  --> $DIR/fn_to_numeric_cast.rs:44:13
    |
 LL |     let _ = abc as u64;
    |             ^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `abc` to `u128`
-  --> $DIR/fn_to_numeric_cast.rs:68:13
+  --> $DIR/fn_to_numeric_cast.rs:45:13
    |
 LL |     let _ = abc as u128;
    |             ^^^^^^^^^^^ help: try: `abc as usize`
 
 error: casting function pointer `f` to `i32`, which truncates the value
-  --> $DIR/fn_to_numeric_cast.rs:76:5
+  --> $DIR/fn_to_numeric_cast.rs:52:5
    |
 LL |     f as i32
    |     ^^^^^^^^ help: try: `f as usize`
diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs
index 09128d8176e..9501eb5da4b 100644
--- a/tests/ui/fn_to_numeric_cast.rs
+++ b/tests/ui/fn_to_numeric_cast.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@stderr-per-bitwidth
 //@no-rustfix
 #![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)]
 
@@ -8,30 +8,17 @@ fn foo() -> String {
 
 fn test_function_to_numeric_cast() {
     let _ = foo as i8;
-    //~^ ERROR: casting function pointer `foo` to `i8`, which truncates the value
-    //~| NOTE: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings`
     let _ = foo as i16;
-    //~^ ERROR: casting function pointer `foo` to `i16`, which truncates the value
     let _ = foo as i32;
-    //~^ ERROR: casting function pointer `foo` to `i32`, which truncates the value
     let _ = foo as i64;
-    //~^ ERROR: casting function pointer `foo` to `i64`
-    //~| NOTE: `-D clippy::fn-to-numeric-cast` implied by `-D warnings`
     let _ = foo as i128;
-    //~^ ERROR: casting function pointer `foo` to `i128`
     let _ = foo as isize;
-    //~^ ERROR: casting function pointer `foo` to `isize`
 
     let _ = foo as u8;
-    //~^ ERROR: casting function pointer `foo` to `u8`, which truncates the value
     let _ = foo as u16;
-    //~^ ERROR: casting function pointer `foo` to `u16`, which truncates the value
     let _ = foo as u32;
-    //~^ ERROR: casting function pointer `foo` to `u32`, which truncates the value
     let _ = foo as u64;
-    //~^ ERROR: casting function pointer `foo` to `u64`
     let _ = foo as u128;
-    //~^ ERROR: casting function pointer `foo` to `u128`
 
     // Casting to usize is OK and should not warn
     let _ = foo as usize;
@@ -45,28 +32,17 @@ fn test_function_var_to_numeric_cast() {
     let abc: fn() -> String = foo;
 
     let _ = abc as i8;
-    //~^ ERROR: casting function pointer `abc` to `i8`, which truncates the value
     let _ = abc as i16;
-    //~^ ERROR: casting function pointer `abc` to `i16`, which truncates the value
     let _ = abc as i32;
-    //~^ ERROR: casting function pointer `abc` to `i32`, which truncates the value
     let _ = abc as i64;
-    //~^ ERROR: casting function pointer `abc` to `i64`
     let _ = abc as i128;
-    //~^ ERROR: casting function pointer `abc` to `i128`
     let _ = abc as isize;
-    //~^ ERROR: casting function pointer `abc` to `isize`
 
     let _ = abc as u8;
-    //~^ ERROR: casting function pointer `abc` to `u8`, which truncates the value
     let _ = abc as u16;
-    //~^ ERROR: casting function pointer `abc` to `u16`, which truncates the value
     let _ = abc as u32;
-    //~^ ERROR: casting function pointer `abc` to `u32`, which truncates the value
     let _ = abc as u64;
-    //~^ ERROR: casting function pointer `abc` to `u64`
     let _ = abc as u128;
-    //~^ ERROR: casting function pointer `abc` to `u128`
 
     // Casting to usize is OK and should not warn
     let _ = abc as usize;
@@ -74,7 +50,6 @@ fn test_function_var_to_numeric_cast() {
 
 fn fn_with_fn_args(f: fn(i32) -> i32) -> i32 {
     f as i32
-    //~^ ERROR: casting function pointer `f` to `i32`, which truncates the value
 }
 
 fn main() {}
diff --git a/tests/ui/fn_to_numeric_cast_32bit.rs b/tests/ui/fn_to_numeric_cast_32bit.rs
deleted file mode 100644
index 93e9361f4dc..00000000000
--- a/tests/ui/fn_to_numeric_cast_32bit.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-//@ignore-64bit
-
-#![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)]
-
-fn foo() -> String {
-    String::new()
-}
-
-fn test_function_to_numeric_cast() {
-    let _ = foo as i8;
-    //~^ ERROR: casting function pointer `foo` to `i8`, which truncates the value
-    //~| NOTE: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings`
-    let _ = foo as i16;
-    //~^ ERROR: casting function pointer `foo` to `i16`, which truncates the value
-    let _ = foo as i32;
-    //~^ ERROR: casting function pointer `foo` to `i32`, which truncates the value
-    let _ = foo as i64;
-    //~^ ERROR: casting function pointer `foo` to `i64`
-    //~| NOTE: `-D clippy::fn-to-numeric-cast` implied by `-D warnings`
-    let _ = foo as i128;
-    //~^ ERROR: casting function pointer `foo` to `i128`
-    let _ = foo as isize;
-    //~^ ERROR: casting function pointer `foo` to `isize`
-
-    let _ = foo as u8;
-    //~^ ERROR: casting function pointer `foo` to `u8`, which truncates the value
-    let _ = foo as u16;
-    //~^ ERROR: casting function pointer `foo` to `u16`, which truncates the value
-    let _ = foo as u32;
-    //~^ ERROR: casting function pointer `foo` to `u32`, which truncates the value
-    let _ = foo as u64;
-    //~^ ERROR: casting function pointer `foo` to `u64`
-    let _ = foo as u128;
-    //~^ ERROR: casting function pointer `foo` to `u128`
-
-    // Casting to usize is OK and should not warn
-    let _ = foo as usize;
-
-    // Cast `f` (a `FnDef`) to `fn()` should not warn
-    fn f() {}
-    let _ = f as fn();
-}
-
-fn test_function_var_to_numeric_cast() {
-    let abc: fn() -> String = foo;
-
-    let _ = abc as i8;
-    //~^ ERROR: casting function pointer `abc` to `i8`, which truncates the value
-    let _ = abc as i16;
-    //~^ ERROR: casting function pointer `abc` to `i16`, which truncates the value
-    let _ = abc as i32;
-    //~^ ERROR: casting function pointer `abc` to `i32`, which truncates the value
-    let _ = abc as i64;
-    //~^ ERROR: casting function pointer `abc` to `i64`
-    let _ = abc as i128;
-    //~^ ERROR: casting function pointer `abc` to `i128`
-    let _ = abc as isize;
-    //~^ ERROR: casting function pointer `abc` to `isize`
-
-    let _ = abc as u8;
-    //~^ ERROR: casting function pointer `abc` to `u8`, which truncates the value
-    let _ = abc as u16;
-    //~^ ERROR: casting function pointer `abc` to `u16`, which truncates the value
-    let _ = abc as u32;
-    //~^ ERROR: casting function pointer `abc` to `u32`, which truncates the value
-    let _ = abc as u64;
-    //~^ ERROR: casting function pointer `abc` to `u64`
-    let _ = abc as u128;
-    //~^ ERROR: casting function pointer `abc` to `u128`
-
-    // Casting to usize is OK and should not warn
-    let _ = abc as usize;
-}
-
-fn fn_with_fn_args(f: fn(i32) -> i32) -> i32 {
-    f as i32
-    //~^ ERROR: casting function pointer `f` to `i32`, which truncates the value
-}
-
-fn main() {}
diff --git a/tests/ui/if_then_some_else_none.rs b/tests/ui/if_then_some_else_none.rs
index 8fa0f34a6c4..77abd663e0a 100644
--- a/tests/ui/if_then_some_else_none.rs
+++ b/tests/ui/if_then_some_else_none.rs
@@ -117,3 +117,15 @@ fn f(b: bool, v: Option<()>) -> Option<()> {
         None
     }
 }
+
+fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
+    let x = if b {
+        #[allow(clippy::let_unit_value)]
+        let _ = v?;
+        Some(())
+    } else {
+        None
+    };
+
+    Ok(())
+}
diff --git a/tests/ui/ignored_unit_patterns.fixed b/tests/ui/ignored_unit_patterns.fixed
index 2912eede4d9..6c6f21fee16 100644
--- a/tests/ui/ignored_unit_patterns.fixed
+++ b/tests/ui/ignored_unit_patterns.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::ignored_unit_patterns)]
-#![allow(clippy::redundant_pattern_matching, clippy::single_match)]
+#![allow(clippy::let_unit_value, clippy::redundant_pattern_matching, clippy::single_match)]
 
 fn foo() -> Result<(), ()> {
     unimplemented!()
@@ -7,9 +7,19 @@ fn foo() -> Result<(), ()> {
 
 fn main() {
     match foo() {
-        Ok(()) => {},
-        Err(()) => {},
+        Ok(()) => {},  //~ ERROR: matching over `()` is more explicit
+        Err(()) => {}, //~ ERROR: matching over `()` is more explicit
     }
     if let Ok(()) = foo() {}
+    //~^ ERROR: matching over `()` is more explicit
     let _ = foo().map_err(|()| todo!());
+    //~^ ERROR: matching over `()` is more explicit
+}
+
+#[allow(unused)]
+pub fn moo(_: ()) {
+    let () = foo().unwrap();
+    //~^ ERROR: matching over `()` is more explicit
+    let _: () = foo().unwrap();
+    let _: () = ();
 }
diff --git a/tests/ui/ignored_unit_patterns.rs b/tests/ui/ignored_unit_patterns.rs
index d180cd8d2fd..5e8c2e03ba2 100644
--- a/tests/ui/ignored_unit_patterns.rs
+++ b/tests/ui/ignored_unit_patterns.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::ignored_unit_patterns)]
-#![allow(clippy::redundant_pattern_matching, clippy::single_match)]
+#![allow(clippy::let_unit_value, clippy::redundant_pattern_matching, clippy::single_match)]
 
 fn foo() -> Result<(), ()> {
     unimplemented!()
@@ -7,9 +7,19 @@ fn foo() -> Result<(), ()> {
 
 fn main() {
     match foo() {
-        Ok(_) => {},
-        Err(_) => {},
+        Ok(_) => {},  //~ ERROR: matching over `()` is more explicit
+        Err(_) => {}, //~ ERROR: matching over `()` is more explicit
     }
     if let Ok(_) = foo() {}
+    //~^ ERROR: matching over `()` is more explicit
     let _ = foo().map_err(|_| todo!());
+    //~^ ERROR: matching over `()` is more explicit
+}
+
+#[allow(unused)]
+pub fn moo(_: ()) {
+    let _ = foo().unwrap();
+    //~^ ERROR: matching over `()` is more explicit
+    let _: () = foo().unwrap();
+    let _: () = ();
 }
diff --git a/tests/ui/ignored_unit_patterns.stderr b/tests/ui/ignored_unit_patterns.stderr
index a8ced22397d..df5e1d89e90 100644
--- a/tests/ui/ignored_unit_patterns.stderr
+++ b/tests/ui/ignored_unit_patterns.stderr
@@ -20,10 +20,16 @@ LL |     if let Ok(_) = foo() {}
    |               ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> $DIR/ignored_unit_patterns.rs:14:28
+  --> $DIR/ignored_unit_patterns.rs:15:28
    |
 LL |     let _ = foo().map_err(|_| todo!());
    |                            ^ help: use `()` instead of `_`: `()`
 
-error: aborting due to 4 previous errors
+error: matching over `()` is more explicit
+  --> $DIR/ignored_unit_patterns.rs:21:9
+   |
+LL |     let _ = foo().unwrap();
+   |         ^ help: use `()` instead of `_`: `()`
+
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/implied_bounds_in_impls.fixed b/tests/ui/implied_bounds_in_impls.fixed
index 952c2b70619..a50fa0ccf6e 100644
--- a/tests/ui/implied_bounds_in_impls.fixed
+++ b/tests/ui/implied_bounds_in_impls.fixed
@@ -65,4 +65,61 @@ impl SomeTrait for SomeStruct {
     }
 }
 
+mod issue11422 {
+    use core::fmt::Debug;
+    // Some additional tests that would cause ICEs:
+
+    // `PartialOrd` has a default generic parameter and does not need to be explicitly specified.
+    // This needs special handling.
+    fn default_generic_param1() -> impl PartialOrd + Debug {}
+    fn default_generic_param2() -> impl PartialOrd + Debug {}
+
+    // Referring to `Self` in the supertrait clause needs special handling.
+    trait Trait1<X: ?Sized> {}
+    trait Trait2: Trait1<Self> {}
+    impl Trait1<()> for () {}
+    impl Trait2 for () {}
+
+    fn f() -> impl Trait1<()> + Trait2 {}
+}
+
+mod issue11435 {
+    // Associated type needs to be included on DoubleEndedIterator in the suggestion
+    fn my_iter() -> impl DoubleEndedIterator<Item = u32> {
+        0..5
+    }
+
+    // Removing the `Clone` bound should include the `+` behind it in its remove suggestion
+    fn f() -> impl Copy {
+        1
+    }
+
+    trait Trait1<T> {
+        type U;
+    }
+    impl Trait1<i32> for () {
+        type U = i64;
+    }
+    trait Trait2<T>: Trait1<T> {}
+    impl Trait2<i32> for () {}
+
+    // When the other trait has generics, it shouldn't add another pair of `<>`
+    fn f2() -> impl Trait2<i32, U = i64> {}
+
+    trait Trait3<T, U, V> {
+        type X;
+        type Y;
+    }
+    trait Trait4<T>: Trait3<T, i16, i64> {}
+    impl Trait3<i8, i16, i64> for () {
+        type X = i32;
+        type Y = i128;
+    }
+    impl Trait4<i8> for () {}
+
+    // Associated type `X` is specified, but `Y` is not, so only that associated type should be moved
+    // over
+    fn f3() -> impl Trait4<i8, X = i32, Y = i128> {}
+}
+
 fn main() {}
diff --git a/tests/ui/implied_bounds_in_impls.rs b/tests/ui/implied_bounds_in_impls.rs
index 475f2621bbf..e74ed4425b8 100644
--- a/tests/ui/implied_bounds_in_impls.rs
+++ b/tests/ui/implied_bounds_in_impls.rs
@@ -65,4 +65,61 @@ impl SomeTrait for SomeStruct {
     }
 }
 
+mod issue11422 {
+    use core::fmt::Debug;
+    // Some additional tests that would cause ICEs:
+
+    // `PartialOrd` has a default generic parameter and does not need to be explicitly specified.
+    // This needs special handling.
+    fn default_generic_param1() -> impl PartialEq + PartialOrd + Debug {}
+    fn default_generic_param2() -> impl PartialOrd + PartialEq + Debug {}
+
+    // Referring to `Self` in the supertrait clause needs special handling.
+    trait Trait1<X: ?Sized> {}
+    trait Trait2: Trait1<Self> {}
+    impl Trait1<()> for () {}
+    impl Trait2 for () {}
+
+    fn f() -> impl Trait1<()> + Trait2 {}
+}
+
+mod issue11435 {
+    // Associated type needs to be included on DoubleEndedIterator in the suggestion
+    fn my_iter() -> impl Iterator<Item = u32> + DoubleEndedIterator {
+        0..5
+    }
+
+    // Removing the `Clone` bound should include the `+` behind it in its remove suggestion
+    fn f() -> impl Copy + Clone {
+        1
+    }
+
+    trait Trait1<T> {
+        type U;
+    }
+    impl Trait1<i32> for () {
+        type U = i64;
+    }
+    trait Trait2<T>: Trait1<T> {}
+    impl Trait2<i32> for () {}
+
+    // When the other trait has generics, it shouldn't add another pair of `<>`
+    fn f2() -> impl Trait1<i32, U = i64> + Trait2<i32> {}
+
+    trait Trait3<T, U, V> {
+        type X;
+        type Y;
+    }
+    trait Trait4<T>: Trait3<T, i16, i64> {}
+    impl Trait3<i8, i16, i64> for () {
+        type X = i32;
+        type Y = i128;
+    }
+    impl Trait4<i8> for () {}
+
+    // Associated type `X` is specified, but `Y` is not, so only that associated type should be moved
+    // over
+    fn f3() -> impl Trait3<i8, i16, i64, X = i32, Y = i128> + Trait4<i8, X = i32> {}
+}
+
 fn main() {}
diff --git a/tests/ui/implied_bounds_in_impls.stderr b/tests/ui/implied_bounds_in_impls.stderr
index e2b1ecb9f1e..72dc2a183a3 100644
--- a/tests/ui/implied_bounds_in_impls.stderr
+++ b/tests/ui/implied_bounds_in_impls.stderr
@@ -120,5 +120,77 @@ LL -     fn f() -> impl Deref + DerefMut<Target = u8> {
 LL +     fn f() -> impl DerefMut<Target = u8> {
    |
 
-error: aborting due to 10 previous errors
+error: this bound is already specified as the supertrait of `PartialOrd`
+  --> $DIR/implied_bounds_in_impls.rs:74:41
+   |
+LL |     fn default_generic_param1() -> impl PartialEq + PartialOrd + Debug {}
+   |                                         ^^^^^^^^^
+   |
+help: try removing this bound
+   |
+LL -     fn default_generic_param1() -> impl PartialEq + PartialOrd + Debug {}
+LL +     fn default_generic_param1() -> impl PartialOrd + Debug {}
+   |
+
+error: this bound is already specified as the supertrait of `PartialOrd`
+  --> $DIR/implied_bounds_in_impls.rs:75:54
+   |
+LL |     fn default_generic_param2() -> impl PartialOrd + PartialEq + Debug {}
+   |                                                      ^^^^^^^^^
+   |
+help: try removing this bound
+   |
+LL -     fn default_generic_param2() -> impl PartialOrd + PartialEq + Debug {}
+LL +     fn default_generic_param2() -> impl PartialOrd + Debug {}
+   |
+
+error: this bound is already specified as the supertrait of `DoubleEndedIterator`
+  --> $DIR/implied_bounds_in_impls.rs:88:26
+   |
+LL |     fn my_iter() -> impl Iterator<Item = u32> + DoubleEndedIterator {
+   |                          ^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing this bound
+   |
+LL -     fn my_iter() -> impl Iterator<Item = u32> + DoubleEndedIterator {
+LL +     fn my_iter() -> impl DoubleEndedIterator<Item = u32> {
+   |
+
+error: this bound is already specified as the supertrait of `Copy`
+  --> $DIR/implied_bounds_in_impls.rs:93:27
+   |
+LL |     fn f() -> impl Copy + Clone {
+   |                           ^^^^^
+   |
+help: try removing this bound
+   |
+LL -     fn f() -> impl Copy + Clone {
+LL +     fn f() -> impl Copy {
+   |
+
+error: this bound is already specified as the supertrait of `Trait2<i32>`
+  --> $DIR/implied_bounds_in_impls.rs:107:21
+   |
+LL |     fn f2() -> impl Trait1<i32, U = i64> + Trait2<i32> {}
+   |                     ^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing this bound
+   |
+LL -     fn f2() -> impl Trait1<i32, U = i64> + Trait2<i32> {}
+LL +     fn f2() -> impl Trait2<i32, U = i64> {}
+   |
+
+error: this bound is already specified as the supertrait of `Trait4<i8, X = i32>`
+  --> $DIR/implied_bounds_in_impls.rs:122:21
+   |
+LL |     fn f3() -> impl Trait3<i8, i16, i64, X = i32, Y = i128> + Trait4<i8, X = i32> {}
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing this bound
+   |
+LL -     fn f3() -> impl Trait3<i8, i16, i64, X = i32, Y = i128> + Trait4<i8, X = i32> {}
+LL +     fn f3() -> impl Trait4<i8, X = i32, Y = i128> {}
+   |
+
+error: aborting due to 16 previous errors
 
diff --git a/tests/ui/iter_out_of_bounds.rs b/tests/ui/iter_out_of_bounds.rs
new file mode 100644
index 00000000000..3cfe6e82fc1
--- /dev/null
+++ b/tests/ui/iter_out_of_bounds.rs
@@ -0,0 +1,71 @@
+//@no-rustfix
+
+#![deny(clippy::iter_out_of_bounds)]
+#![allow(clippy::useless_vec)]
+
+fn opaque_empty_iter() -> impl Iterator<Item = ()> {
+    std::iter::empty()
+}
+
+fn main() {
+    #[allow(clippy::never_loop)]
+    for _ in [1, 2, 3].iter().skip(4) {
+        //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+        unreachable!();
+    }
+    for (i, _) in [1, 2, 3].iter().take(4).enumerate() {
+        //~^ ERROR: this `.take()` call takes more items than the iterator will produce
+        assert!(i <= 2);
+    }
+
+    #[allow(clippy::needless_borrow)]
+    for _ in (&&&&&&[1, 2, 3]).iter().take(4) {}
+    //~^ ERROR: this `.take()` call takes more items than the iterator will produce
+
+    for _ in [1, 2, 3].iter().skip(4) {}
+    //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+
+    for _ in [1; 3].iter().skip(4) {}
+    //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+
+    // Should not lint
+    for _ in opaque_empty_iter().skip(1) {}
+
+    for _ in vec![1, 2, 3].iter().skip(4) {}
+    //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+
+    for _ in vec![1; 3].iter().skip(4) {}
+    //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+
+    let x = [1, 2, 3];
+    for _ in x.iter().skip(4) {}
+    //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+
+    let n = 4;
+    for _ in x.iter().skip(n) {}
+    //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+
+    let empty = std::iter::empty::<i8>;
+
+    for _ in empty().skip(1) {}
+    //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+
+    for _ in empty().take(1) {}
+    //~^ ERROR: this `.take()` call takes more items than the iterator will produce
+
+    for _ in std::iter::once(1).skip(2) {}
+    //~^ ERROR: this `.skip()` call skips more items than the iterator will produce
+
+    for _ in std::iter::once(1).take(2) {}
+    //~^ ERROR: this `.take()` call takes more items than the iterator will produce
+
+    for x in [].iter().take(1) {
+        //~^ ERROR: this `.take()` call takes more items than the iterator will produce
+        let _: &i32 = x;
+    }
+
+    // ok, not out of bounds
+    for _ in [1].iter().take(1) {}
+    for _ in [1, 2, 3].iter().take(2) {}
+    for _ in [1, 2, 3].iter().skip(2) {}
+}
diff --git a/tests/ui/iter_out_of_bounds.stderr b/tests/ui/iter_out_of_bounds.stderr
new file mode 100644
index 00000000000..f235faec8e5
--- /dev/null
+++ b/tests/ui/iter_out_of_bounds.stderr
@@ -0,0 +1,119 @@
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:12:14
+   |
+LL |     for _ in [1, 2, 3].iter().skip(4) {
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+note: the lint level is defined here
+  --> $DIR/iter_out_of_bounds.rs:3:9
+   |
+LL | #![deny(clippy::iter_out_of_bounds)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this `.take()` call takes more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:16:19
+   |
+LL |     for (i, _) in [1, 2, 3].iter().take(4).enumerate() {
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and the returned iterator will simply yield the same items
+
+error: this `.take()` call takes more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:22:14
+   |
+LL |     for _ in (&&&&&&[1, 2, 3]).iter().take(4) {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and the returned iterator will simply yield the same items
+
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:25:14
+   |
+LL |     for _ in [1, 2, 3].iter().skip(4) {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:28:14
+   |
+LL |     for _ in [1; 3].iter().skip(4) {}
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:34:14
+   |
+LL |     for _ in vec![1, 2, 3].iter().skip(4) {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:37:14
+   |
+LL |     for _ in vec![1; 3].iter().skip(4) {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:41:14
+   |
+LL |     for _ in x.iter().skip(4) {}
+   |              ^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:45:14
+   |
+LL |     for _ in x.iter().skip(n) {}
+   |              ^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:50:14
+   |
+LL |     for _ in empty().skip(1) {}
+   |              ^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+
+error: this `.take()` call takes more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:53:14
+   |
+LL |     for _ in empty().take(1) {}
+   |              ^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and the returned iterator will simply yield the same items
+
+error: this `.skip()` call skips more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:56:14
+   |
+LL |     for _ in std::iter::once(1).skip(2) {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and will create an empty iterator
+
+error: this `.take()` call takes more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:59:14
+   |
+LL |     for _ in std::iter::once(1).take(2) {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and the returned iterator will simply yield the same items
+
+error: this `.take()` call takes more items than the iterator will produce
+  --> $DIR/iter_out_of_bounds.rs:62:14
+   |
+LL |     for x in [].iter().take(1) {
+   |              ^^^^^^^^^^^^^^^^^
+   |
+   = note: this operation is useless and the returned iterator will simply yield the same items
+
+error: aborting due to 14 previous errors
+
diff --git a/tests/ui/iter_overeager_cloned.fixed b/tests/ui/iter_overeager_cloned.fixed
index 9dd046fec1f..7d8a584b022 100644
--- a/tests/ui/iter_overeager_cloned.fixed
+++ b/tests/ui/iter_overeager_cloned.fixed
@@ -63,11 +63,9 @@ fn main() {
 
     let _ = vec.iter().for_each(|x| assert!(!x.is_empty()));
 
-    // Not implemented yet
-    let _ = vec.iter().cloned().all(|x| x.len() == 1);
+    let _ = vec.iter().all(|x| x.len() == 1);
 
-    // Not implemented yet
-    let _ = vec.iter().cloned().any(|x| x.len() == 1);
+    let _ = vec.iter().any(|x| x.len() == 1);
 
     // Should probably stay as it is.
     let _ = [0, 1, 2, 3, 4].iter().cloned().take(10);
diff --git a/tests/ui/iter_overeager_cloned.rs b/tests/ui/iter_overeager_cloned.rs
index 3cab3669554..58c374ab8cd 100644
--- a/tests/ui/iter_overeager_cloned.rs
+++ b/tests/ui/iter_overeager_cloned.rs
@@ -64,10 +64,8 @@ fn main() {
 
     let _ = vec.iter().cloned().for_each(|x| assert!(!x.is_empty()));
 
-    // Not implemented yet
     let _ = vec.iter().cloned().all(|x| x.len() == 1);
 
-    // Not implemented yet
     let _ = vec.iter().cloned().any(|x| x.len() == 1);
 
     // Should probably stay as it is.
diff --git a/tests/ui/iter_overeager_cloned.stderr b/tests/ui/iter_overeager_cloned.stderr
index fbcd33066d8..a9a739688eb 100644
--- a/tests/ui/iter_overeager_cloned.stderr
+++ b/tests/ui/iter_overeager_cloned.stderr
@@ -148,5 +148,21 @@ LL |     let _ = vec.iter().cloned().for_each(|x| assert!(!x.is_empty()));
    |                       |
    |                       help: try: `.for_each(|x| assert!(!x.is_empty()))`
 
-error: aborting due to 17 previous errors
+error: unneeded cloning of iterator items
+  --> $DIR/iter_overeager_cloned.rs:67:13
+   |
+LL |     let _ = vec.iter().cloned().all(|x| x.len() == 1);
+   |             ^^^^^^^^^^-------------------------------
+   |                       |
+   |                       help: try: `.all(|x| x.len() == 1)`
+
+error: unneeded cloning of iterator items
+  --> $DIR/iter_overeager_cloned.rs:69:13
+   |
+LL |     let _ = vec.iter().cloned().any(|x| x.len() == 1);
+   |             ^^^^^^^^^^-------------------------------
+   |                       |
+   |                       help: try: `.any(|x| x.len() == 1)`
+
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/iter_skip_next.fixed b/tests/ui/iter_skip_next.fixed
index 310b24a9cde..3e41b363249 100644
--- a/tests/ui/iter_skip_next.fixed
+++ b/tests/ui/iter_skip_next.fixed
@@ -4,6 +4,7 @@
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::iter_nth)]
 #![allow(clippy::useless_vec)]
+#![allow(clippy::iter_out_of_bounds)]
 #![allow(unused_mut, dead_code)]
 
 extern crate option_helpers;
diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs
index 222d6a2a184..6d96441ca96 100644
--- a/tests/ui/iter_skip_next.rs
+++ b/tests/ui/iter_skip_next.rs
@@ -4,6 +4,7 @@
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::iter_nth)]
 #![allow(clippy::useless_vec)]
+#![allow(clippy::iter_out_of_bounds)]
 #![allow(unused_mut, dead_code)]
 
 extern crate option_helpers;
diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr
index 0b6bf652b1f..39b173e7586 100644
--- a/tests/ui/iter_skip_next.stderr
+++ b/tests/ui/iter_skip_next.stderr
@@ -1,5 +1,5 @@
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:16:28
+  --> $DIR/iter_skip_next.rs:17:28
    |
 LL |     let _ = some_vec.iter().skip(42).next();
    |                            ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)`
@@ -8,37 +8,37 @@ LL |     let _ = some_vec.iter().skip(42).next();
    = help: to override `-D warnings` add `#[allow(clippy::iter_skip_next)]`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:17:36
+  --> $DIR/iter_skip_next.rs:18:36
    |
 LL |     let _ = some_vec.iter().cycle().skip(42).next();
    |                                    ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:18:20
+  --> $DIR/iter_skip_next.rs:19:20
    |
 LL |     let _ = (1..10).skip(10).next();
    |                    ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:19:33
+  --> $DIR/iter_skip_next.rs:20:33
    |
 LL |     let _ = &some_vec[..].iter().skip(3).next();
    |                                 ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(3)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:27:26
+  --> $DIR/iter_skip_next.rs:28:26
    |
 LL |     let _: Vec<&str> = sp.skip(1).next().unwrap().split(' ').collect();
    |                          ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:29:29
+  --> $DIR/iter_skip_next.rs:30:29
    |
 LL |         let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect();
    |                             ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:35:29
+  --> $DIR/iter_skip_next.rs:36:29
    |
 LL |         let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect();
    |                             ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)`
diff --git a/tests/ui/iter_skip_next_unfixable.rs b/tests/ui/iter_skip_next_unfixable.rs
index 9c224f4117d..6c98bdc8c88 100644
--- a/tests/ui/iter_skip_next_unfixable.rs
+++ b/tests/ui/iter_skip_next_unfixable.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::iter_skip_next)]
-#![allow(dead_code)]
+#![allow(dead_code, clippy::iter_out_of_bounds)]
 //@no-rustfix
 /// Checks implementation of `ITER_SKIP_NEXT` lint
 fn main() {
diff --git a/tests/ui/iter_skip_zero.fixed b/tests/ui/iter_skip_zero.fixed
index 62a83d5905b..447d07100e9 100644
--- a/tests/ui/iter_skip_zero.fixed
+++ b/tests/ui/iter_skip_zero.fixed
@@ -1,5 +1,5 @@
 //@aux-build:proc_macros.rs
-#![allow(clippy::useless_vec, unused)]
+#![allow(clippy::useless_vec, clippy::iter_out_of_bounds, unused)]
 #![warn(clippy::iter_skip_zero)]
 
 #[macro_use]
diff --git a/tests/ui/iter_skip_zero.rs b/tests/ui/iter_skip_zero.rs
index c96696dde65..ba63c398180 100644
--- a/tests/ui/iter_skip_zero.rs
+++ b/tests/ui/iter_skip_zero.rs
@@ -1,5 +1,5 @@
 //@aux-build:proc_macros.rs
-#![allow(clippy::useless_vec, unused)]
+#![allow(clippy::useless_vec, clippy::iter_out_of_bounds, unused)]
 #![warn(clippy::iter_skip_zero)]
 
 #[macro_use]
diff --git a/tests/ui/large_enum_variant.32bit.stderr b/tests/ui/large_enum_variant.32bit.stderr
new file mode 100644
index 00000000000..0e0eee21cf3
--- /dev/null
+++ b/tests/ui/large_enum_variant.32bit.stderr
@@ -0,0 +1,280 @@
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:11:1
+   |
+LL | / enum LargeEnum {
+LL | |     A(i32),
+   | |     ------ the second-largest variant contains at least 4 bytes
+LL | |     B([i32; 8000]),
+   | |     -------------- the largest variant contains at least 32000 bytes
+LL | | }
+   | |_^ the entire enum is at least 32004 bytes
+   |
+   = note: `-D clippy::large-enum-variant` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::large_enum_variant)]`
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     B(Box<[i32; 8000]>),
+   |       ~~~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:35:1
+   |
+LL | / enum LargeEnum2 {
+LL | |     VariantOk(i32, u32),
+   | |     ------------------- the second-largest variant contains at least 8 bytes
+LL | |     ContainingLargeEnum(LargeEnum),
+   | |     ------------------------------ the largest variant contains at least 32004 bytes
+LL | | }
+   | |_^ the entire enum is at least 32004 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     ContainingLargeEnum(Box<LargeEnum>),
+   |                         ~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:40:1
+   |
+LL | / enum LargeEnum3 {
+LL | |     ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]),
+   | |     --------------------------------------------------------- the largest variant contains at least 70004 bytes
+LL | |     VoidVariant,
+LL | |     StructLikeLittle { x: i32, y: i32 },
+   | |     ----------------------------------- the second-largest variant contains at least 8 bytes
+LL | | }
+   | |_^ the entire enum is at least 70008 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>),
+   |                                     ~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:46:1
+   |
+LL | / enum LargeEnum4 {
+LL | |     VariantOk(i32, u32),
+   | |     ------------------- the second-largest variant contains at least 8 bytes
+LL | |     StructLikeLarge { x: [i32; 8000], y: i32 },
+   | |     ------------------------------------------ the largest variant contains at least 32004 bytes
+LL | | }
+   | |_^ the entire enum is at least 32008 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     StructLikeLarge { x: Box<[i32; 8000]>, y: i32 },
+   |                          ~~~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:51:1
+   |
+LL | / enum LargeEnum5 {
+LL | |     VariantOk(i32, u32),
+   | |     ------------------- the second-largest variant contains at least 8 bytes
+LL | |     StructLikeLarge2 { x: [i32; 8000] },
+   | |     ----------------------------------- the largest variant contains at least 32000 bytes
+LL | | }
+   | |_^ the entire enum is at least 32004 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     StructLikeLarge2 { x: Box<[i32; 8000]> },
+   |                           ~~~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:67:1
+   |
+LL | / enum LargeEnum7 {
+LL | |     A,
+LL | |     B([u8; 1255]),
+   | |     ------------- the largest variant contains at least 1255 bytes
+LL | |     C([u8; 200]),
+   | |     ------------ the second-largest variant contains at least 200 bytes
+LL | | }
+   | |_^ the entire enum is at least 1256 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     B(Box<[u8; 1255]>),
+   |       ~~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:73:1
+   |
+LL | / enum LargeEnum8 {
+LL | |     VariantOk(i32, u32),
+   | |     ------------------- the second-largest variant contains at least 8 bytes
+LL | |     ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]),
+   | |     ------------------------------------------------------------------------- the largest variant contains at least 70128 bytes
+LL | | }
+   | |_^ the entire enum is at least 70132 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]),
+   |                                ~~~~~~~~~~~~~~~~            ~~~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:78:1
+   |
+LL | / enum LargeEnum9 {
+LL | |     A(Struct<()>),
+   | |     ------------- the second-largest variant contains at least 4 bytes
+LL | |     B(Struct2),
+   | |     ---------- the largest variant contains at least 32000 bytes
+LL | | }
+   | |_^ the entire enum is at least 32004 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     B(Box<Struct2>),
+   |       ~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:83:1
+   |
+LL | / enum LargeEnumOk2<T> {
+LL | |     A(T),
+   | |     ---- the second-largest variant contains at least 0 bytes
+LL | |     B(Struct2),
+   | |     ---------- the largest variant contains at least 32000 bytes
+LL | | }
+   | |_^ the entire enum is at least 32000 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     B(Box<Struct2>),
+   |       ~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:88:1
+   |
+LL | / enum LargeEnumOk3<T> {
+LL | |     A(Struct<T>),
+   | |     ------------ the second-largest variant contains at least 4 bytes
+LL | |     B(Struct2),
+   | |     ---------- the largest variant contains at least 32000 bytes
+LL | | }
+   | |_^ the entire enum is at least 32000 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     B(Box<Struct2>),
+   |       ~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:103:1
+   |
+LL | / enum CopyableLargeEnum {
+LL | |     A(bool),
+   | |     ------- the second-largest variant contains at least 1 bytes
+LL | |     B([u64; 8000]),
+   | |     -------------- the largest variant contains at least 64000 bytes
+LL | | }
+   | |_^ the entire enum is at least 64004 bytes
+   |
+note: boxing a variant would require the type no longer be `Copy`
+  --> $DIR/large_enum_variant.rs:103:6
+   |
+LL | enum CopyableLargeEnum {
+   |      ^^^^^^^^^^^^^^^^^
+help: consider boxing the large fields to reduce the total size of the enum
+  --> $DIR/large_enum_variant.rs:105:5
+   |
+LL |     B([u64; 8000]),
+   |     ^^^^^^^^^^^^^^
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:108:1
+   |
+LL | / enum ManuallyCopyLargeEnum {
+LL | |     A(bool),
+   | |     ------- the second-largest variant contains at least 1 bytes
+LL | |     B([u64; 8000]),
+   | |     -------------- the largest variant contains at least 64000 bytes
+LL | | }
+   | |_^ the entire enum is at least 64004 bytes
+   |
+note: boxing a variant would require the type no longer be `Copy`
+  --> $DIR/large_enum_variant.rs:108:6
+   |
+LL | enum ManuallyCopyLargeEnum {
+   |      ^^^^^^^^^^^^^^^^^^^^^
+help: consider boxing the large fields to reduce the total size of the enum
+  --> $DIR/large_enum_variant.rs:110:5
+   |
+LL |     B([u64; 8000]),
+   |     ^^^^^^^^^^^^^^
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:121:1
+   |
+LL | / enum SomeGenericPossiblyCopyEnum<T> {
+LL | |     A(bool, std::marker::PhantomData<T>),
+   | |     ------------------------------------ the second-largest variant contains at least 1 bytes
+LL | |     B([u64; 4000]),
+   | |     -------------- the largest variant contains at least 32000 bytes
+LL | | }
+   | |_^ the entire enum is at least 32004 bytes
+   |
+note: boxing a variant would require the type no longer be `Copy`
+  --> $DIR/large_enum_variant.rs:121:6
+   |
+LL | enum SomeGenericPossiblyCopyEnum<T> {
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider boxing the large fields to reduce the total size of the enum
+  --> $DIR/large_enum_variant.rs:123:5
+   |
+LL |     B([u64; 4000]),
+   |     ^^^^^^^^^^^^^^
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:134:1
+   |
+LL | / enum LargeEnumWithGenerics<T> {
+LL | |     Small,
+   | |     ----- the second-largest variant carries no data at all
+LL | |     Large((T, [u8; 512])),
+   | |     --------------------- the largest variant contains at least 512 bytes
+LL | | }
+   | |_^ the entire enum is at least 512 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     Large(Box<(T, [u8; 512])>),
+   |           ~~~~~~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:143:1
+   |
+LL | / enum WithGenerics {
+LL | |     Large([Foo<u64>; 64]),
+   | |     --------------------- the largest variant contains at least 512 bytes
+LL | |     Small(u8),
+   | |     --------- the second-largest variant contains at least 1 bytes
+LL | | }
+   | |_^ the entire enum is at least 516 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     Large(Box<[Foo<u64>; 64]>),
+   |           ~~~~~~~~~~~~~~~~~~~
+
+error: large size difference between variants
+  --> $DIR/large_enum_variant.rs:153:1
+   |
+LL | / enum LargeEnumOfConst {
+LL | |     Ok,
+   | |     -- the second-largest variant carries no data at all
+LL | |     Error(PossiblyLargeEnumWithConst<256>),
+   | |     -------------------------------------- the largest variant contains at least 514 bytes
+LL | | }
+   | |_^ the entire enum is at least 514 bytes
+   |
+help: consider boxing the large fields to reduce the total size of the enum
+   |
+LL |     Error(Box<PossiblyLargeEnumWithConst<256>>),
+   |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 16 previous errors
+
diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.64bit.stderr
similarity index 91%
rename from tests/ui/large_enum_variant.stderr
rename to tests/ui/large_enum_variant.64bit.stderr
index 7026ca785f3..3eba43e05ec 100644
--- a/tests/ui/large_enum_variant.stderr
+++ b/tests/ui/large_enum_variant.64bit.stderr
@@ -1,5 +1,5 @@
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:10:1
+  --> $DIR/large_enum_variant.rs:11:1
    |
 LL | / enum LargeEnum {
 LL | |     A(i32),
@@ -17,7 +17,7 @@ LL |     B(Box<[i32; 8000]>),
    |       ~~~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:34:1
+  --> $DIR/large_enum_variant.rs:35:1
    |
 LL | / enum LargeEnum2 {
 LL | |     VariantOk(i32, u32),
@@ -33,7 +33,7 @@ LL |     ContainingLargeEnum(Box<LargeEnum>),
    |                         ~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:39:1
+  --> $DIR/large_enum_variant.rs:40:1
    |
 LL | / enum LargeEnum3 {
 LL | |     ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]),
@@ -50,7 +50,7 @@ LL |     ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>),
    |                                     ~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:45:1
+  --> $DIR/large_enum_variant.rs:46:1
    |
 LL | / enum LargeEnum4 {
 LL | |     VariantOk(i32, u32),
@@ -66,7 +66,7 @@ LL |     StructLikeLarge { x: Box<[i32; 8000]>, y: i32 },
    |                          ~~~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:50:1
+  --> $DIR/large_enum_variant.rs:51:1
    |
 LL | / enum LargeEnum5 {
 LL | |     VariantOk(i32, u32),
@@ -82,7 +82,7 @@ LL |     StructLikeLarge2 { x: Box<[i32; 8000]> },
    |                           ~~~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:66:1
+  --> $DIR/large_enum_variant.rs:67:1
    |
 LL | / enum LargeEnum7 {
 LL | |     A,
@@ -99,7 +99,7 @@ LL |     B(Box<[u8; 1255]>),
    |       ~~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:72:1
+  --> $DIR/large_enum_variant.rs:73:1
    |
 LL | / enum LargeEnum8 {
 LL | |     VariantOk(i32, u32),
@@ -115,7 +115,7 @@ LL |     ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>
    |                                ~~~~~~~~~~~~~~~~            ~~~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:77:1
+  --> $DIR/large_enum_variant.rs:78:1
    |
 LL | / enum LargeEnum9 {
 LL | |     A(Struct<()>),
@@ -131,7 +131,7 @@ LL |     B(Box<Struct2>),
    |       ~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:82:1
+  --> $DIR/large_enum_variant.rs:83:1
    |
 LL | / enum LargeEnumOk2<T> {
 LL | |     A(T),
@@ -147,7 +147,7 @@ LL |     B(Box<Struct2>),
    |       ~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:87:1
+  --> $DIR/large_enum_variant.rs:88:1
    |
 LL | / enum LargeEnumOk3<T> {
 LL | |     A(Struct<T>),
@@ -163,7 +163,7 @@ LL |     B(Box<Struct2>),
    |       ~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:102:1
+  --> $DIR/large_enum_variant.rs:103:1
    |
 LL | / enum CopyableLargeEnum {
 LL | |     A(bool),
@@ -174,18 +174,18 @@ LL | | }
    | |_^ the entire enum is at least 64008 bytes
    |
 note: boxing a variant would require the type no longer be `Copy`
-  --> $DIR/large_enum_variant.rs:102:6
+  --> $DIR/large_enum_variant.rs:103:6
    |
 LL | enum CopyableLargeEnum {
    |      ^^^^^^^^^^^^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
-  --> $DIR/large_enum_variant.rs:104:5
+  --> $DIR/large_enum_variant.rs:105:5
    |
 LL |     B([u64; 8000]),
    |     ^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:107:1
+  --> $DIR/large_enum_variant.rs:108:1
    |
 LL | / enum ManuallyCopyLargeEnum {
 LL | |     A(bool),
@@ -196,18 +196,18 @@ LL | | }
    | |_^ the entire enum is at least 64008 bytes
    |
 note: boxing a variant would require the type no longer be `Copy`
-  --> $DIR/large_enum_variant.rs:107:6
+  --> $DIR/large_enum_variant.rs:108:6
    |
 LL | enum ManuallyCopyLargeEnum {
    |      ^^^^^^^^^^^^^^^^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
-  --> $DIR/large_enum_variant.rs:109:5
+  --> $DIR/large_enum_variant.rs:110:5
    |
 LL |     B([u64; 8000]),
    |     ^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:120:1
+  --> $DIR/large_enum_variant.rs:121:1
    |
 LL | / enum SomeGenericPossiblyCopyEnum<T> {
 LL | |     A(bool, std::marker::PhantomData<T>),
@@ -218,18 +218,18 @@ LL | | }
    | |_^ the entire enum is at least 32008 bytes
    |
 note: boxing a variant would require the type no longer be `Copy`
-  --> $DIR/large_enum_variant.rs:120:6
+  --> $DIR/large_enum_variant.rs:121:6
    |
 LL | enum SomeGenericPossiblyCopyEnum<T> {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
-  --> $DIR/large_enum_variant.rs:122:5
+  --> $DIR/large_enum_variant.rs:123:5
    |
 LL |     B([u64; 4000]),
    |     ^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:133:1
+  --> $DIR/large_enum_variant.rs:134:1
    |
 LL | / enum LargeEnumWithGenerics<T> {
 LL | |     Small,
@@ -245,7 +245,7 @@ LL |     Large(Box<(T, [u8; 512])>),
    |           ~~~~~~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:142:1
+  --> $DIR/large_enum_variant.rs:143:1
    |
 LL | / enum WithGenerics {
 LL | |     Large([Foo<u64>; 64]),
@@ -261,7 +261,7 @@ LL |     Large(Box<[Foo<u64>; 64]>),
    |           ~~~~~~~~~~~~~~~~~~~
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:152:1
+  --> $DIR/large_enum_variant.rs:153:1
    |
 LL | / enum LargeEnumOfConst {
 LL | |     Ok,
diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs
index f101bda76a8..3625c011dbf 100644
--- a/tests/ui/large_enum_variant.rs
+++ b/tests/ui/large_enum_variant.rs
@@ -1,3 +1,4 @@
+//@stderr-per-bitwidth
 //@aux-build:proc_macros.rs
 //@no-rustfix
 #![allow(dead_code)]
diff --git a/tests/ui/manual_range_patterns.fixed b/tests/ui/manual_range_patterns.fixed
index ea06e27d153..b348d7071f6 100644
--- a/tests/ui/manual_range_patterns.fixed
+++ b/tests/ui/manual_range_patterns.fixed
@@ -13,8 +13,8 @@ fn main() {
     let _ = matches!(f, 1 | 2147483647);
     let _ = matches!(f, 0 | 2147483647);
     let _ = matches!(f, -2147483647 | 2147483647);
-    let _ = matches!(f, 1 | (2..=4));
-    let _ = matches!(f, 1 | (2..4));
+    let _ = matches!(f, 1..=4);
+    let _ = matches!(f, 1..4);
     let _ = matches!(f, 1..=48324729);
     let _ = matches!(f, 0..=48324730);
     let _ = matches!(f, 0..=3);
@@ -25,9 +25,20 @@ fn main() {
     };
     let _ = matches!(f, -5..=3);
     let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1); // 2 is missing
-    let _ = matches!(f, -1000001..=1000001);
+    let _ = matches!(f, -1_000_001..=1_000_001);
     let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_002);
 
+    matches!(f, 0x00..=0x03);
+    matches!(f, 0x00..=0x07);
+    matches!(f, -0x09..=0x00);
+
+    matches!(f, 0..=5);
+    matches!(f, 0..5);
+
+    matches!(f, 0..10);
+    matches!(f, 0..=10);
+    matches!(f, 0..=10);
+
     macro_rules! mac {
         ($e:expr) => {
             matches!($e, 1..=10)
diff --git a/tests/ui/manual_range_patterns.rs b/tests/ui/manual_range_patterns.rs
index eb29987b89f..a0750f54b73 100644
--- a/tests/ui/manual_range_patterns.rs
+++ b/tests/ui/manual_range_patterns.rs
@@ -28,6 +28,17 @@ fn main() {
     let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001);
     let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_002);
 
+    matches!(f, 0x00 | 0x01 | 0x02 | 0x03);
+    matches!(f, 0x00..=0x05 | 0x06 | 0x07);
+    matches!(f, -0x09 | -0x08 | -0x07..=0x00);
+
+    matches!(f, 0..5 | 5);
+    matches!(f, 0 | 1..5);
+
+    matches!(f, 0..=5 | 6..10);
+    matches!(f, 0..5 | 5..=10);
+    matches!(f, 5..=10 | 0..5);
+
     macro_rules! mac {
         ($e:expr) => {
             matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
diff --git a/tests/ui/manual_range_patterns.stderr b/tests/ui/manual_range_patterns.stderr
index 3eee39af86e..fbeb9455769 100644
--- a/tests/ui/manual_range_patterns.stderr
+++ b/tests/ui/manual_range_patterns.stderr
@@ -13,6 +13,18 @@ error: this OR pattern can be rewritten using a range
 LL |     let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
 
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:16:25
+   |
+LL |     let _ = matches!(f, 1 | (2..=4));
+   |                         ^^^^^^^^^^^ help: try: `1..=4`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:17:25
+   |
+LL |     let _ = matches!(f, 1 | (2..4));
+   |                         ^^^^^^^^^^ help: try: `1..4`
+
 error: this OR pattern can be rewritten using a range
   --> $DIR/manual_range_patterns.rs:18:25
    |
@@ -47,10 +59,58 @@ error: this OR pattern can be rewritten using a range
   --> $DIR/manual_range_patterns.rs:28:25
    |
 LL |     let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001);
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1000001..=1000001`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1_000_001..=1_000_001`
 
 error: this OR pattern can be rewritten using a range
-  --> $DIR/manual_range_patterns.rs:33:26
+  --> $DIR/manual_range_patterns.rs:31:17
+   |
+LL |     matches!(f, 0x00 | 0x01 | 0x02 | 0x03);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x03`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:32:17
+   |
+LL |     matches!(f, 0x00..=0x05 | 0x06 | 0x07);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x07`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:33:17
+   |
+LL |     matches!(f, -0x09 | -0x08 | -0x07..=0x00);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-0x09..=0x00`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:35:17
+   |
+LL |     matches!(f, 0..5 | 5);
+   |                 ^^^^^^^^ help: try: `0..=5`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:36:17
+   |
+LL |     matches!(f, 0 | 1..5);
+   |                 ^^^^^^^^ help: try: `0..5`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:38:17
+   |
+LL |     matches!(f, 0..=5 | 6..10);
+   |                 ^^^^^^^^^^^^^ help: try: `0..10`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:39:17
+   |
+LL |     matches!(f, 0..5 | 5..=10);
+   |                 ^^^^^^^^^^^^^ help: try: `0..=10`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:40:17
+   |
+LL |     matches!(f, 5..=10 | 0..5);
+   |                 ^^^^^^^^^^^^^ help: try: `0..=10`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:44:26
    |
 LL |             matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
@@ -60,5 +120,5 @@ LL |     mac!(f);
    |
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 9 previous errors
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/missing_asserts_for_indexing.fixed b/tests/ui/missing_asserts_for_indexing.fixed
new file mode 100644
index 00000000000..a96827259f5
--- /dev/null
+++ b/tests/ui/missing_asserts_for_indexing.fixed
@@ -0,0 +1,121 @@
+#![allow(unused)]
+#![warn(clippy::missing_asserts_for_indexing)]
+
+// ok
+fn sum_with_assert(v: &[u8]) -> u8 {
+    assert!(v.len() > 4);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+}
+
+// ok
+fn sum_with_assert_other_way(v: &[u8]) -> u8 {
+    assert!(5 <= v.len());
+    v[0] + v[1] + v[2] + v[3] + v[4]
+}
+
+// ok
+fn sum_with_assert_ge(v: &[u8]) -> u8 {
+    assert!(v.len() >= 5);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+}
+
+// ok
+fn sum_with_assert_ge_other_way(v: &[u8]) -> u8 {
+    assert!(4 < v.len());
+    v[0] + v[1] + v[2] + v[3] + v[4]
+}
+
+fn sum_with_assert_lt(v: &[u8]) -> u8 {
+    assert!(v.len() > 4);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+
+fn sum_with_assert_le(v: &[u8]) -> u8 {
+    assert!(v.len() > 4);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+
+fn sum_with_incorrect_assert_len(v: &[u8]) -> u8 {
+    assert!(v.len() > 4);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+
+fn sum_with_incorrect_assert_len2(v: &[u8]) -> u8 {
+    assert!(v.len() > 4);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+
+// ok, don't lint for single array access
+fn single_access(v: &[u8]) -> u8 {
+    v[0]
+}
+
+// ok
+fn subslice_ok(v: &[u8]) {
+    assert!(v.len() > 3);
+    let _ = v[0];
+    let _ = v[1..4];
+}
+
+fn subslice_bad(v: &[u8]) {
+    assert!(v.len() > 3);
+    let _ = v[0];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+    let _ = v[1..4];
+}
+
+// ok
+fn subslice_inclusive_ok(v: &[u8]) {
+    assert!(v.len() > 4);
+    let _ = v[0];
+    let _ = v[1..=4];
+}
+
+fn subslice_inclusive_bad(v: &[u8]) {
+    assert!(v.len() > 4);
+    let _ = v[0];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+    let _ = v[1..=4];
+}
+
+fn index_different_slices_ok(v1: &[u8], v2: &[u8]) {
+    assert!(v1.len() > 12);
+    assert!(v2.len() > 15);
+    let _ = v1[0] + v1[12];
+    let _ = v2[5] + v2[15];
+}
+
+fn index_different_slices_wrong_len(v1: &[u8], v2: &[u8]) {
+    assert!(v1.len() > 12);
+    assert!(v2.len() > 15);
+    let _ = v1[0] + v1[12];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+    let _ = v2[5] + v2[15];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+fn index_different_slices_one_wrong_len(v1: &[u8], v2: &[u8]) {
+    assert!(v1.len() > 12);
+    assert!(v2.len() > 15);
+    let _ = v1[0] + v1[12];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+    let _ = v2[5] + v2[15];
+}
+
+fn side_effect() -> &'static [u8] {
+    &[]
+}
+
+fn index_side_effect_expr() {
+    let _ = side_effect()[0] + side_effect()[1];
+}
+
+// ok, single access for different slices
+fn index_different_slice_in_same_expr(v1: &[u8], v2: &[u8]) {
+    let _ = v1[0] + v2[1];
+}
+
+fn main() {}
diff --git a/tests/ui/missing_asserts_for_indexing.rs b/tests/ui/missing_asserts_for_indexing.rs
new file mode 100644
index 00000000000..0b4b883acf8
--- /dev/null
+++ b/tests/ui/missing_asserts_for_indexing.rs
@@ -0,0 +1,121 @@
+#![allow(unused)]
+#![warn(clippy::missing_asserts_for_indexing)]
+
+// ok
+fn sum_with_assert(v: &[u8]) -> u8 {
+    assert!(v.len() > 4);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+}
+
+// ok
+fn sum_with_assert_other_way(v: &[u8]) -> u8 {
+    assert!(5 <= v.len());
+    v[0] + v[1] + v[2] + v[3] + v[4]
+}
+
+// ok
+fn sum_with_assert_ge(v: &[u8]) -> u8 {
+    assert!(v.len() >= 5);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+}
+
+// ok
+fn sum_with_assert_ge_other_way(v: &[u8]) -> u8 {
+    assert!(4 < v.len());
+    v[0] + v[1] + v[2] + v[3] + v[4]
+}
+
+fn sum_with_assert_lt(v: &[u8]) -> u8 {
+    assert!(v.len() < 5);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+
+fn sum_with_assert_le(v: &[u8]) -> u8 {
+    assert!(v.len() <= 5);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+
+fn sum_with_incorrect_assert_len(v: &[u8]) -> u8 {
+    assert!(v.len() > 3);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+
+fn sum_with_incorrect_assert_len2(v: &[u8]) -> u8 {
+    assert!(v.len() >= 4);
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+
+// ok, don't lint for single array access
+fn single_access(v: &[u8]) -> u8 {
+    v[0]
+}
+
+// ok
+fn subslice_ok(v: &[u8]) {
+    assert!(v.len() > 3);
+    let _ = v[0];
+    let _ = v[1..4];
+}
+
+fn subslice_bad(v: &[u8]) {
+    assert!(v.len() >= 3);
+    let _ = v[0];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+    let _ = v[1..4];
+}
+
+// ok
+fn subslice_inclusive_ok(v: &[u8]) {
+    assert!(v.len() > 4);
+    let _ = v[0];
+    let _ = v[1..=4];
+}
+
+fn subslice_inclusive_bad(v: &[u8]) {
+    assert!(v.len() >= 4);
+    let _ = v[0];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+    let _ = v[1..=4];
+}
+
+fn index_different_slices_ok(v1: &[u8], v2: &[u8]) {
+    assert!(v1.len() > 12);
+    assert!(v2.len() > 15);
+    let _ = v1[0] + v1[12];
+    let _ = v2[5] + v2[15];
+}
+
+fn index_different_slices_wrong_len(v1: &[u8], v2: &[u8]) {
+    assert!(v1.len() >= 12);
+    assert!(v2.len() >= 15);
+    let _ = v1[0] + v1[12];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+    let _ = v2[5] + v2[15];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+}
+fn index_different_slices_one_wrong_len(v1: &[u8], v2: &[u8]) {
+    assert!(v1.len() >= 12);
+    assert!(v2.len() > 15);
+    let _ = v1[0] + v1[12];
+    //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
+    let _ = v2[5] + v2[15];
+}
+
+fn side_effect() -> &'static [u8] {
+    &[]
+}
+
+fn index_side_effect_expr() {
+    let _ = side_effect()[0] + side_effect()[1];
+}
+
+// ok, single access for different slices
+fn index_different_slice_in_same_expr(v1: &[u8], v2: &[u8]) {
+    let _ = v1[0] + v2[1];
+}
+
+fn main() {}
diff --git a/tests/ui/missing_asserts_for_indexing.stderr b/tests/ui/missing_asserts_for_indexing.stderr
new file mode 100644
index 00000000000..a3e66d7958e
--- /dev/null
+++ b/tests/ui/missing_asserts_for_indexing.stderr
@@ -0,0 +1,253 @@
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:30:5
+   |
+LL |     assert!(v.len() < 5);
+   |     -------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:30:5
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:30:12
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |            ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:30:19
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                   ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:30:26
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                          ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:30:33
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                                 ^^^^
+   = note: asserting the length before indexing will elide bounds checks
+   = note: `-D clippy::missing-asserts-for-indexing` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::missing_asserts_for_indexing)]`
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:36:5
+   |
+LL |     assert!(v.len() <= 5);
+   |     --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:36:5
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:36:12
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |            ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:36:19
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                   ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:36:26
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                          ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:36:33
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                                 ^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:42:5
+   |
+LL |     assert!(v.len() > 3);
+   |     -------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:42:5
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:42:12
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |            ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:42:19
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                   ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:42:26
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                          ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:42:33
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                                 ^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:48:5
+   |
+LL |     assert!(v.len() >= 4);
+   |     --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:48:5
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:48:12
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |            ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:48:19
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                   ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:48:26
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                          ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:48:33
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                                 ^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:66:13
+   |
+LL |       assert!(v.len() >= 3);
+   |       --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 3)`
+LL |       let _ = v[0];
+   |  _____________^
+LL | |
+LL | |     let _ = v[1..4];
+   | |___________________^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:66:13
+   |
+LL |     let _ = v[0];
+   |             ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:68:13
+   |
+LL |     let _ = v[1..4];
+   |             ^^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:80:13
+   |
+LL |       assert!(v.len() >= 4);
+   |       --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
+LL |       let _ = v[0];
+   |  _____________^
+LL | |
+LL | |     let _ = v[1..=4];
+   | |____________________^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:80:13
+   |
+LL |     let _ = v[0];
+   |             ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:82:13
+   |
+LL |     let _ = v[1..=4];
+   |             ^^^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:95:13
+   |
+LL |     assert!(v1.len() >= 12);
+   |     ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() > 12)`
+LL |     assert!(v2.len() >= 15);
+LL |     let _ = v1[0] + v1[12];
+   |             ^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:95:13
+   |
+LL |     let _ = v1[0] + v1[12];
+   |             ^^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:95:21
+   |
+LL |     let _ = v1[0] + v1[12];
+   |                     ^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:97:13
+   |
+LL |     assert!(v2.len() >= 15);
+   |     ----------------------- help: provide the highest index that is indexed with: `assert!(v2.len() > 15)`
+...
+LL |     let _ = v2[5] + v2[15];
+   |             ^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:97:13
+   |
+LL |     let _ = v2[5] + v2[15];
+   |             ^^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:97:21
+   |
+LL |     let _ = v2[5] + v2[15];
+   |                     ^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> $DIR/missing_asserts_for_indexing.rs:103:13
+   |
+LL |     assert!(v1.len() >= 12);
+   |     ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() > 12)`
+LL |     assert!(v2.len() > 15);
+LL |     let _ = v1[0] + v1[12];
+   |             ^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:103:13
+   |
+LL |     let _ = v1[0] + v1[12];
+   |             ^^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing.rs:103:21
+   |
+LL |     let _ = v1[0] + v1[12];
+   |                     ^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/missing_asserts_for_indexing_unfixable.rs b/tests/ui/missing_asserts_for_indexing_unfixable.rs
new file mode 100644
index 00000000000..4346ed892f2
--- /dev/null
+++ b/tests/ui/missing_asserts_for_indexing_unfixable.rs
@@ -0,0 +1,49 @@
+#![allow(unused)]
+#![warn(clippy::missing_asserts_for_indexing)]
+
+fn sum(v: &[u8]) -> u8 {
+    v[0] + v[1] + v[2] + v[3] + v[4]
+    //~^ ERROR: indexing into a slice multiple times without an `assert`
+}
+
+fn subslice(v: &[u8]) {
+    let _ = v[0];
+    //~^ ERROR: indexing into a slice multiple times without an `assert`
+    let _ = v[1..4];
+}
+
+fn variables(v: &[u8]) -> u8 {
+    let a = v[0];
+    //~^ ERROR: indexing into a slice multiple times without an `assert`
+    let b = v[1];
+    let c = v[2];
+    a + b + c
+}
+
+fn index_different_slices(v1: &[u8], v2: &[u8]) {
+    let _ = v1[0] + v1[12];
+    let _ = v2[5] + v2[15];
+}
+
+fn index_different_slices2(v1: &[u8], v2: &[u8]) {
+    assert!(v1.len() > 12);
+    let _ = v1[0] + v1[12];
+    let _ = v2[5] + v2[15];
+}
+
+struct Foo<'a> {
+    v: &'a [u8],
+    v2: &'a [u8],
+}
+
+fn index_struct_field(f: &Foo<'_>) {
+    let _ = f.v[0] + f.v[1];
+    //~^ ERROR: indexing into a slice multiple times without an `assert`
+}
+
+fn index_struct_different_fields(f: &Foo<'_>) {
+    // ok, different fields
+    let _ = f.v[0] + f.v2[1];
+}
+
+fn main() {}
diff --git a/tests/ui/missing_asserts_for_indexing_unfixable.stderr b/tests/ui/missing_asserts_for_indexing_unfixable.stderr
new file mode 100644
index 00000000000..12c9eed5d66
--- /dev/null
+++ b/tests/ui/missing_asserts_for_indexing_unfixable.stderr
@@ -0,0 +1,164 @@
+error: indexing into a slice multiple times without an `assert`
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:5:5
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:5:5
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |     ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:5:12
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |            ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:5:19
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                   ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:5:26
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                          ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:5:33
+   |
+LL |     v[0] + v[1] + v[2] + v[3] + v[4]
+   |                                 ^^^^
+   = note: asserting the length before indexing will elide bounds checks
+   = note: `-D clippy::missing-asserts-for-indexing` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::missing_asserts_for_indexing)]`
+
+error: indexing into a slice multiple times without an `assert`
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:10:13
+   |
+LL |       let _ = v[0];
+   |  _____________^
+LL | |
+LL | |     let _ = v[1..4];
+   | |___________________^
+   |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 3);`
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:10:13
+   |
+LL |     let _ = v[0];
+   |             ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:12:13
+   |
+LL |     let _ = v[1..4];
+   |             ^^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times without an `assert`
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:16:13
+   |
+LL |       let a = v[0];
+   |  _____________^
+LL | |
+LL | |     let b = v[1];
+LL | |     let c = v[2];
+   | |________________^
+   |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 2);`
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:16:13
+   |
+LL |     let a = v[0];
+   |             ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:18:13
+   |
+LL |     let b = v[1];
+   |             ^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:19:13
+   |
+LL |     let c = v[2];
+   |             ^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times without an `assert`
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:24:13
+   |
+LL |     let _ = v1[0] + v1[12];
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: consider asserting the length before indexing: `assert!(v1.len() > 12);`
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:24:13
+   |
+LL |     let _ = v1[0] + v1[12];
+   |             ^^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:24:21
+   |
+LL |     let _ = v1[0] + v1[12];
+   |                     ^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times without an `assert`
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:25:13
+   |
+LL |     let _ = v2[5] + v2[15];
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: consider asserting the length before indexing: `assert!(v2.len() > 15);`
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:25:13
+   |
+LL |     let _ = v2[5] + v2[15];
+   |             ^^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:25:21
+   |
+LL |     let _ = v2[5] + v2[15];
+   |                     ^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times without an `assert`
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:31:13
+   |
+LL |     let _ = v2[5] + v2[15];
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: consider asserting the length before indexing: `assert!(v2.len() > 15);`
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:31:13
+   |
+LL |     let _ = v2[5] + v2[15];
+   |             ^^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:31:21
+   |
+LL |     let _ = v2[5] + v2[15];
+   |                     ^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times without an `assert`
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:40:13
+   |
+LL |     let _ = f.v[0] + f.v[1];
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: consider asserting the length before indexing: `assert!(f.v.len() > 1);`
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:40:13
+   |
+LL |     let _ = f.v[0] + f.v[1];
+   |             ^^^^^^
+note: slice indexed here
+  --> $DIR/missing_asserts_for_indexing_unfixable.rs:40:22
+   |
+LL |     let _ = f.v[0] + f.v[1];
+   |                      ^^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed
index ee67224b4a8..0a52b25229d 100644
--- a/tests/ui/needless_borrow.fixed
+++ b/tests/ui/needless_borrow.fixed
@@ -503,3 +503,16 @@ mod issue_10535 {
     {
     }
 }
+
+mod issue_10253 {
+    struct S;
+    trait X {
+        fn f<T>(&self);
+    }
+    impl X for &S {
+        fn f<T>(&self) {}
+    }
+    fn f() {
+        (&S).f::<()>();
+    }
+}
diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs
index 1444f47d920..34a95d18463 100644
--- a/tests/ui/needless_borrow.rs
+++ b/tests/ui/needless_borrow.rs
@@ -503,3 +503,16 @@ mod issue_10535 {
     {
     }
 }
+
+mod issue_10253 {
+    struct S;
+    trait X {
+        fn f<T>(&self);
+    }
+    impl X for &S {
+        fn f<T>(&self) {}
+    }
+    fn f() {
+        (&S).f::<()>();
+    }
+}
diff --git a/tests/ui/needless_raw_string.fixed b/tests/ui/needless_raw_string.fixed
index 4db375178b4..85549810513 100644
--- a/tests/ui/needless_raw_string.fixed
+++ b/tests/ui/needless_raw_string.fixed
@@ -9,8 +9,13 @@ fn main() {
     b"aaa";
     br#""aaa""#;
     br#"\s"#;
-    // currently disabled: https://github.com/rust-lang/rust/issues/113333
-    // cr#"aaa"#;
-    // cr#""aaa""#;
-    // cr#"\s"#;
+    c"aaa";
+    cr#""aaa""#;
+    cr#"\s"#;
+
+    "
+        a
+        multiline
+        string
+    ";
 }
diff --git a/tests/ui/needless_raw_string.rs b/tests/ui/needless_raw_string.rs
index 59c75fda41b..06d49730387 100644
--- a/tests/ui/needless_raw_string.rs
+++ b/tests/ui/needless_raw_string.rs
@@ -9,8 +9,13 @@ fn main() {
     br#"aaa"#;
     br#""aaa""#;
     br#"\s"#;
-    // currently disabled: https://github.com/rust-lang/rust/issues/113333
-    // cr#"aaa"#;
-    // cr#""aaa""#;
-    // cr#"\s"#;
+    cr#"aaa"#;
+    cr#""aaa""#;
+    cr#"\s"#;
+
+    r#"
+        a
+        multiline
+        string
+    "#;
 }
diff --git a/tests/ui/needless_raw_string.stderr b/tests/ui/needless_raw_string.stderr
index 83cc6d332ee..e6806b31b1d 100644
--- a/tests/ui/needless_raw_string.stderr
+++ b/tests/ui/needless_raw_string.stderr
@@ -2,16 +2,58 @@ error: unnecessary raw string literal
   --> $DIR/needless_raw_string.rs:6:5
    |
 LL |     r#"aaa"#;
-   |     ^^^^^^^^ help: try: `"aaa"`
+   |     ^^^^^^^^
    |
    = note: `-D clippy::needless-raw-strings` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::needless_raw_strings)]`
+help: try
+   |
+LL -     r#"aaa"#;
+LL +     "aaa";
+   |
 
 error: unnecessary raw string literal
   --> $DIR/needless_raw_string.rs:9:5
    |
 LL |     br#"aaa"#;
-   |     ^^^^^^^^^ help: try: `b"aaa"`
+   |     ^^^^^^^^^
+   |
+help: try
+   |
+LL -     br#"aaa"#;
+LL +     b"aaa";
+   |
 
-error: aborting due to 2 previous errors
+error: unnecessary raw string literal
+  --> $DIR/needless_raw_string.rs:12:5
+   |
+LL |     cr#"aaa"#;
+   |     ^^^^^^^^^
+   |
+help: try
+   |
+LL -     cr#"aaa"#;
+LL +     c"aaa";
+   |
+
+error: unnecessary raw string literal
+  --> $DIR/needless_raw_string.rs:16:5
+   |
+LL | /     r#"
+LL | |         a
+LL | |         multiline
+LL | |         string
+LL | |     "#;
+   | |______^
+   |
+help: try
+   |
+LL ~     "
+LL |         a
+LL |         multiline
+LL |         string
+LL ~     ";
+   |
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed
index 84902157ab4..e980adeeff4 100644
--- a/tests/ui/needless_raw_string_hashes.fixed
+++ b/tests/ui/needless_raw_string_hashes.fixed
@@ -3,17 +3,22 @@
 #![feature(c_str_literals)]
 
 fn main() {
-    r#"aaa"#;
+    r"\aaa";
     r#"Hello "world"!"#;
     r####" "### "## "# "####;
     r###" "aa" "# "## "###;
-    br#"aaa"#;
+    br"\aaa";
     br#"Hello "world"!"#;
     br####" "### "## "# "####;
     br###" "aa" "# "## "###;
-    // currently disabled: https://github.com/rust-lang/rust/issues/113333
-    // cr#"aaa"#;
-    // cr##"Hello "world"!"##;
-    // cr######" "### "## "# "######;
-    // cr######" "aa" "# "## "######;
+    cr"\aaa";
+    cr#"Hello "world"!"#;
+    cr####" "### "## "# "####;
+    cr###" "aa" "# "## "###;
+
+    r"
+        \a
+        multiline
+        string
+    ";
 }
diff --git a/tests/ui/needless_raw_string_hashes.rs b/tests/ui/needless_raw_string_hashes.rs
index 62abae83859..6113c5f25ae 100644
--- a/tests/ui/needless_raw_string_hashes.rs
+++ b/tests/ui/needless_raw_string_hashes.rs
@@ -3,17 +3,22 @@
 #![feature(c_str_literals)]
 
 fn main() {
-    r#"aaa"#;
+    r#"\aaa"#;
     r##"Hello "world"!"##;
     r######" "### "## "# "######;
     r######" "aa" "# "## "######;
-    br#"aaa"#;
+    br#"\aaa"#;
     br##"Hello "world"!"##;
     br######" "### "## "# "######;
     br######" "aa" "# "## "######;
-    // currently disabled: https://github.com/rust-lang/rust/issues/113333
-    // cr#"aaa"#;
-    // cr##"Hello "world"!"##;
-    // cr######" "### "## "# "######;
-    // cr######" "aa" "# "## "######;
+    cr#"\aaa"#;
+    cr##"Hello "world"!"##;
+    cr######" "### "## "# "######;
+    cr######" "aa" "# "## "######;
+
+    r#"
+        \a
+        multiline
+        string
+    "#;
 }
diff --git a/tests/ui/needless_raw_string_hashes.stderr b/tests/ui/needless_raw_string_hashes.stderr
index 94c51c423b8..5a8e3d04543 100644
--- a/tests/ui/needless_raw_string_hashes.stderr
+++ b/tests/ui/needless_raw_string_hashes.stderr
@@ -1,41 +1,167 @@
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:6:5
+   |
+LL |     r#"\aaa"#;
+   |     ^^^^^^^^^
+   |
+   = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::needless_raw_string_hashes)]`
+help: remove all the hashes around the literal
+   |
+LL -     r#"\aaa"#;
+LL +     r"\aaa";
+   |
+
 error: unnecessary hashes around raw string literal
   --> $DIR/needless_raw_string_hashes.rs:7:5
    |
 LL |     r##"Hello "world"!"##;
-   |     ^^^^^^^^^^^^^^^^^^^^^ help: try: `r#"Hello "world"!"#`
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove one hash from both sides of the literal
+   |
+LL -     r##"Hello "world"!"##;
+LL +     r#"Hello "world"!"#;
    |
-   = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_raw_string_hashes)]`
 
 error: unnecessary hashes around raw string literal
   --> $DIR/needless_raw_string_hashes.rs:8:5
    |
 LL |     r######" "### "## "# "######;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r####" "### "## "# "####`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove 2 hashes from both sides of the literal
+   |
+LL -     r######" "### "## "# "######;
+LL +     r####" "### "## "# "####;
+   |
 
 error: unnecessary hashes around raw string literal
   --> $DIR/needless_raw_string_hashes.rs:9:5
    |
 LL |     r######" "aa" "# "## "######;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r###" "aa" "# "## "###`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove 3 hashes from both sides of the literal
+   |
+LL -     r######" "aa" "# "## "######;
+LL +     r###" "aa" "# "## "###;
+   |
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:10:5
+   |
+LL |     br#"\aaa"#;
+   |     ^^^^^^^^^^
+   |
+help: remove all the hashes around the literal
+   |
+LL -     br#"\aaa"#;
+LL +     br"\aaa";
+   |
 
 error: unnecessary hashes around raw string literal
   --> $DIR/needless_raw_string_hashes.rs:11:5
    |
 LL |     br##"Hello "world"!"##;
-   |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `br#"Hello "world"!"#`
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove one hash from both sides of the literal
+   |
+LL -     br##"Hello "world"!"##;
+LL +     br#"Hello "world"!"#;
+   |
 
 error: unnecessary hashes around raw string literal
   --> $DIR/needless_raw_string_hashes.rs:12:5
    |
 LL |     br######" "### "## "# "######;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br####" "### "## "# "####`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove 2 hashes from both sides of the literal
+   |
+LL -     br######" "### "## "# "######;
+LL +     br####" "### "## "# "####;
+   |
 
 error: unnecessary hashes around raw string literal
   --> $DIR/needless_raw_string_hashes.rs:13:5
    |
 LL |     br######" "aa" "# "## "######;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br###" "aa" "# "## "###`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove 3 hashes from both sides of the literal
+   |
+LL -     br######" "aa" "# "## "######;
+LL +     br###" "aa" "# "## "###;
+   |
 
-error: aborting due to 6 previous errors
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:14:5
+   |
+LL |     cr#"\aaa"#;
+   |     ^^^^^^^^^^
+   |
+help: remove all the hashes around the literal
+   |
+LL -     cr#"\aaa"#;
+LL +     cr"\aaa";
+   |
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:15:5
+   |
+LL |     cr##"Hello "world"!"##;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove one hash from both sides of the literal
+   |
+LL -     cr##"Hello "world"!"##;
+LL +     cr#"Hello "world"!"#;
+   |
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:16:5
+   |
+LL |     cr######" "### "## "# "######;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove 2 hashes from both sides of the literal
+   |
+LL -     cr######" "### "## "# "######;
+LL +     cr####" "### "## "# "####;
+   |
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:17:5
+   |
+LL |     cr######" "aa" "# "## "######;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove 3 hashes from both sides of the literal
+   |
+LL -     cr######" "aa" "# "## "######;
+LL +     cr###" "aa" "# "## "###;
+   |
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:19:5
+   |
+LL | /     r#"
+LL | |         \a
+LL | |         multiline
+LL | |         string
+LL | |     "#;
+   | |______^
+   |
+help: remove all the hashes around the literal
+   |
+LL ~     r"
+LL |         \a
+LL |         multiline
+LL |         string
+LL ~     ";
+   |
+
+error: aborting due to 13 previous errors
 
diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs
index 001b94391ca..c67a6d4494e 100644
--- a/tests/ui/never_loop.rs
+++ b/tests/ui/never_loop.rs
@@ -337,10 +337,8 @@ pub fn test26() {
 
 pub fn test27() {
     loop {
-        //~^ ERROR: this loop never actually loops
         'label: {
             let x = true;
-            // Lints because we cannot prove it's always `true`
             if x {
                 break 'label;
             }
@@ -349,6 +347,59 @@ pub fn test27() {
     }
 }
 
+// issue 11004
+pub fn test29() {
+    loop {
+        'label: {
+            if true {
+                break 'label;
+            }
+            return;
+        }
+    }
+}
+
+pub fn test30() {
+    'a: loop {
+        'b: {
+            for j in 0..2 {
+                if j == 1 {
+                    break 'b;
+                }
+            }
+            break 'a;
+        }
+    }
+}
+
+pub fn test31(b: bool) {
+    'a: loop {
+        'b: {
+            'c: loop {
+                //~^ ERROR: this loop never actually loops
+                if b { break 'c } else { break 'b }
+            }
+            continue 'a;
+        }
+        break 'a;
+    }
+}
+
+pub fn test32() {
+    loop {
+        //~^ ERROR: this loop never actually loops
+        panic!("oh no");
+    }
+    loop {
+        //~^ ERROR: this loop never actually loops
+        unimplemented!("not yet");
+    }
+    loop {
+        // no error
+        todo!("maybe later");
+    }
+}
+
 fn main() {
     test1();
     test2();
diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr
index 234780007b1..3982f36cea9 100644
--- a/tests/ui/never_loop.stderr
+++ b/tests/ui/never_loop.stderr
@@ -154,16 +154,31 @@ LL |             if let Some(_) = (0..20).next() {
    |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:339:5
+  --> $DIR/never_loop.rs:378:13
+   |
+LL | /             'c: loop {
+LL | |
+LL | |                 if b { break 'c } else { break 'b }
+LL | |             }
+   | |_____________^
+
+error: this loop never actually loops
+  --> $DIR/never_loop.rs:389:5
    |
 LL | /     loop {
 LL | |
-LL | |         'label: {
-LL | |             let x = true;
-...  |
-LL | |         }
+LL | |         panic!("oh no");
 LL | |     }
    | |_____^
 
-error: aborting due to 14 previous errors
+error: this loop never actually loops
+  --> $DIR/never_loop.rs:393:5
+   |
+LL | /     loop {
+LL | |
+LL | |         unimplemented!("not yet");
+LL | |     }
+   | |_____^
+
+error: aborting due to 16 previous errors
 
diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.fixed b/tests/ui/non_canonical_clone_impl.fixed
similarity index 100%
rename from tests/ui/incorrect_clone_impl_on_copy_type.fixed
rename to tests/ui/non_canonical_clone_impl.fixed
diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.rs b/tests/ui/non_canonical_clone_impl.rs
similarity index 100%
rename from tests/ui/incorrect_clone_impl_on_copy_type.rs
rename to tests/ui/non_canonical_clone_impl.rs
diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.stderr b/tests/ui/non_canonical_clone_impl.stderr
similarity index 54%
rename from tests/ui/incorrect_clone_impl_on_copy_type.stderr
rename to tests/ui/non_canonical_clone_impl.stderr
index 566a1a4b14b..44196751b05 100644
--- a/tests/ui/incorrect_clone_impl_on_copy_type.stderr
+++ b/tests/ui/non_canonical_clone_impl.stderr
@@ -1,5 +1,5 @@
-error: incorrect implementation of `clone` on a `Copy` type
-  --> $DIR/incorrect_clone_impl_on_copy_type.rs:9:29
+error: non-canonical implementation of `clone` on a `Copy` type
+  --> $DIR/non_canonical_clone_impl.rs:9:29
    |
 LL |       fn clone(&self) -> Self {
    |  _____________________________^
@@ -7,10 +7,11 @@ LL | |         Self(self.0)
 LL | |     }
    | |_____^ help: change this to: `{ *self }`
    |
-   = note: `#[deny(clippy::incorrect_clone_impl_on_copy_type)]` on by default
+   = note: `-D clippy::non-canonical-clone-impl` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::non_canonical_clone_impl)]`
 
-error: incorrect implementation of `clone_from` on a `Copy` type
-  --> $DIR/incorrect_clone_impl_on_copy_type.rs:13:5
+error: unnecessary implementation of `clone_from` on a `Copy` type
+  --> $DIR/non_canonical_clone_impl.rs:13:5
    |
 LL | /     fn clone_from(&mut self, source: &Self) {
 LL | |         source.clone();
@@ -18,8 +19,8 @@ LL | |         *self = source.clone();
 LL | |     }
    | |_____^ help: remove it
 
-error: incorrect implementation of `clone` on a `Copy` type
-  --> $DIR/incorrect_clone_impl_on_copy_type.rs:80:29
+error: non-canonical implementation of `clone` on a `Copy` type
+  --> $DIR/non_canonical_clone_impl.rs:80:29
    |
 LL |       fn clone(&self) -> Self {
    |  _____________________________^
@@ -27,8 +28,8 @@ LL | |         Self(self.0)
 LL | |     }
    | |_____^ help: change this to: `{ *self }`
 
-error: incorrect implementation of `clone_from` on a `Copy` type
-  --> $DIR/incorrect_clone_impl_on_copy_type.rs:84:5
+error: unnecessary implementation of `clone_from` on a `Copy` type
+  --> $DIR/non_canonical_clone_impl.rs:84:5
    |
 LL | /     fn clone_from(&mut self, source: &Self) {
 LL | |         source.clone();
diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type.fixed b/tests/ui/non_canonical_partial_ord_impl.fixed
similarity index 100%
rename from tests/ui/incorrect_partial_ord_impl_on_ord_type.fixed
rename to tests/ui/non_canonical_partial_ord_impl.fixed
diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type.rs b/tests/ui/non_canonical_partial_ord_impl.rs
similarity index 100%
rename from tests/ui/incorrect_partial_ord_impl_on_ord_type.rs
rename to tests/ui/non_canonical_partial_ord_impl.rs
diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr b/tests/ui/non_canonical_partial_ord_impl.stderr
similarity index 63%
rename from tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr
rename to tests/ui/non_canonical_partial_ord_impl.stderr
index 1f706984662..05cc717b9ba 100644
--- a/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr
+++ b/tests/ui/non_canonical_partial_ord_impl.stderr
@@ -1,5 +1,5 @@
-error: incorrect implementation of `partial_cmp` on an `Ord` type
-  --> $DIR/incorrect_partial_ord_impl_on_ord_type.rs:16:1
+error: non-canonical implementation of `partial_cmp` on an `Ord` type
+  --> $DIR/non_canonical_partial_ord_impl.rs:16:1
    |
 LL | /  impl PartialOrd for A {
 LL | |      fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@@ -10,10 +10,11 @@ LL | ||     }
 LL | |  }
    | |__^
    |
-   = note: `#[deny(clippy::incorrect_partial_ord_impl_on_ord_type)]` on by default
+   = note: `-D clippy::non-canonical-partial-ord-impl` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::non_canonical_partial_ord_impl)]`
 
-error: incorrect implementation of `partial_cmp` on an `Ord` type
-  --> $DIR/incorrect_partial_ord_impl_on_ord_type.rs:50:1
+error: non-canonical implementation of `partial_cmp` on an `Ord` type
+  --> $DIR/non_canonical_partial_ord_impl.rs:50:1
    |
 LL | / impl PartialOrd for C {
 LL | |     fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type_fully_qual.rs b/tests/ui/non_canonical_partial_ord_impl_fully_qual.rs
similarity index 82%
rename from tests/ui/incorrect_partial_ord_impl_on_ord_type_fully_qual.rs
rename to tests/ui/non_canonical_partial_ord_impl_fully_qual.rs
index 1173a95d065..2f8d5cf30c7 100644
--- a/tests/ui/incorrect_partial_ord_impl_on_ord_type_fully_qual.rs
+++ b/tests/ui/non_canonical_partial_ord_impl_fully_qual.rs
@@ -21,8 +21,6 @@ impl cmp::Ord for A {
 }
 
 impl PartialOrd for A {
-    //~^ ERROR: incorrect implementation of `partial_cmp` on an `Ord` type
-    //~| NOTE: `#[deny(clippy::incorrect_partial_ord_impl_on_ord_type)]` on by default
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         // NOTE: This suggestion is wrong, as `Ord` is not in scope. But this should be fine as it isn't
         // automatically applied
@@ -46,7 +44,6 @@ impl cmp::Ord for B {
 }
 
 impl PartialOrd for B {
-    //~^ ERROR: incorrect implementation of `partial_cmp` on an `Ord` type
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         // This calls `B.cmp`, not `Ord::cmp`!
         Some(self.cmp(other))
diff --git a/tests/ui/incorrect_partial_ord_impl_on_ord_type_fully_qual.stderr b/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr
similarity index 67%
rename from tests/ui/incorrect_partial_ord_impl_on_ord_type_fully_qual.stderr
rename to tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr
index 09d7a32e334..4978d7a8739 100644
--- a/tests/ui/incorrect_partial_ord_impl_on_ord_type_fully_qual.stderr
+++ b/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr
@@ -1,9 +1,7 @@
-error: incorrect implementation of `partial_cmp` on an `Ord` type
-  --> $DIR/incorrect_partial_ord_impl_on_ord_type_fully_qual.rs:23:1
+error: non-canonical implementation of `partial_cmp` on an `Ord` type
+  --> $DIR/non_canonical_partial_ord_impl_fully_qual.rs:23:1
    |
 LL | /  impl PartialOrd for A {
-LL | |
-LL | |
 LL | |      fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
    | | _____________________________________________________________-
 LL | ||         // NOTE: This suggestion is wrong, as `Ord` is not in scope. But this should be fine as it isn't
@@ -14,13 +12,13 @@ LL | ||     }
 LL | |  }
    | |__^
    |
-   = note: `#[deny(clippy::incorrect_partial_ord_impl_on_ord_type)]` on by default
+   = note: `-D clippy::non-canonical-partial-ord-impl` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::non_canonical_partial_ord_impl)]`
 
-error: incorrect implementation of `partial_cmp` on an `Ord` type
-  --> $DIR/incorrect_partial_ord_impl_on_ord_type_fully_qual.rs:48:1
+error: non-canonical implementation of `partial_cmp` on an `Ord` type
+  --> $DIR/non_canonical_partial_ord_impl_fully_qual.rs:46:1
    |
 LL | /  impl PartialOrd for B {
-LL | |
 LL | |      fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
    | | _____________________________________________________________-
 LL | ||         // This calls `B.cmp`, not `Ord::cmp`!
diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed
index 0fd68eb92b1..4df9be2c21d 100644
--- a/tests/ui/rename.fixed
+++ b/tests/ui/rename.fixed
@@ -14,6 +14,8 @@
 #![allow(clippy::mixed_read_write_in_expression)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
+#![allow(clippy::non_canonical_clone_impl)]
+#![allow(clippy::non_canonical_partial_ord_impl)]
 #![allow(clippy::arithmetic_side_effects)]
 #![allow(clippy::overly_complex_bool_expr)]
 #![allow(clippy::new_without_default)]
@@ -33,10 +35,10 @@
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
+#![allow(useless_ptr_null_checks)]
 #![allow(for_loops_over_fallibles)]
 #![allow(forgetting_copy_types)]
 #![allow(forgetting_references)]
-#![allow(useless_ptr_null_checks)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -62,6 +64,8 @@
 #![warn(clippy::mixed_read_write_in_expression)]
 #![warn(clippy::useless_conversion)]
 #![warn(clippy::match_result_ok)]
+#![warn(clippy::non_canonical_clone_impl)]
+#![warn(clippy::non_canonical_partial_ord_impl)]
 #![warn(clippy::arithmetic_side_effects)]
 #![warn(clippy::overly_complex_bool_expr)]
 #![warn(clippy::new_without_default)]
@@ -85,12 +89,12 @@
 #![warn(drop_bounds)]
 #![warn(dropping_copy_types)]
 #![warn(dropping_references)]
+#![warn(useless_ptr_null_checks)]
 #![warn(for_loops_over_fallibles)]
 #![warn(for_loops_over_fallibles)]
 #![warn(for_loops_over_fallibles)]
 #![warn(forgetting_copy_types)]
 #![warn(forgetting_references)]
-#![warn(useless_ptr_null_checks)]
 #![warn(array_into_iter)]
 #![warn(invalid_atomic_ordering)]
 #![warn(invalid_value)]
diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs
index 927937fba83..940e60068e7 100644
--- a/tests/ui/rename.rs
+++ b/tests/ui/rename.rs
@@ -14,6 +14,8 @@
 #![allow(clippy::mixed_read_write_in_expression)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
+#![allow(clippy::non_canonical_clone_impl)]
+#![allow(clippy::non_canonical_partial_ord_impl)]
 #![allow(clippy::arithmetic_side_effects)]
 #![allow(clippy::overly_complex_bool_expr)]
 #![allow(clippy::new_without_default)]
@@ -33,10 +35,10 @@
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
+#![allow(useless_ptr_null_checks)]
 #![allow(for_loops_over_fallibles)]
 #![allow(forgetting_copy_types)]
 #![allow(forgetting_references)]
-#![allow(useless_ptr_null_checks)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -62,6 +64,8 @@
 #![warn(clippy::eval_order_dependence)]
 #![warn(clippy::identity_conversion)]
 #![warn(clippy::if_let_some_result)]
+#![warn(clippy::incorrect_clone_impl_on_copy_type)]
+#![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
 #![warn(clippy::integer_arithmetic)]
 #![warn(clippy::logic_bug)]
 #![warn(clippy::new_without_default_derive)]
@@ -85,12 +89,12 @@
 #![warn(clippy::drop_bounds)]
 #![warn(clippy::drop_copy)]
 #![warn(clippy::drop_ref)]
+#![warn(clippy::fn_null_check)]
 #![warn(clippy::for_loop_over_option)]
 #![warn(clippy::for_loop_over_result)]
 #![warn(clippy::for_loops_over_fallibles)]
 #![warn(clippy::forget_copy)]
 #![warn(clippy::forget_ref)]
-#![warn(clippy::fn_null_check)]
 #![warn(clippy::into_iter_on_array)]
 #![warn(clippy::invalid_atomic_ordering)]
 #![warn(clippy::invalid_ref)]
diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr
index d98fc7b30db..30824e154b8 100644
--- a/tests/ui/rename.stderr
+++ b/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -8,322 +8,334 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:59: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:58:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
+error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
+  --> $DIR/rename.rs:67:9
+   |
+LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
+
+error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
+  --> $DIR/rename.rs:68:9
+   |
+LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
+
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:74: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:71:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::unwrap_or_else_default)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:83:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> $DIR/rename.rs:84:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::cmp_nan)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
+error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
+  --> $DIR/rename.rs:92:9
+   |
+LL | #![warn(clippy::fn_null_check)]
+   |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
+
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:97:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
-error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
-  --> $DIR/rename.rs:93:9
-   |
-LL | #![warn(clippy::fn_null_check)]
-   |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
-
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:98:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:95:9
+  --> $DIR/rename.rs:99:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:96:9
+  --> $DIR/rename.rs:100:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> $DIR/rename.rs:97:9
+  --> $DIR/rename.rs:101:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:98:9
+  --> $DIR/rename.rs:102:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:99:9
+  --> $DIR/rename.rs:103:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:100:9
+  --> $DIR/rename.rs:104:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:101:9
+  --> $DIR/rename.rs:105:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:102:9
+  --> $DIR/rename.rs:106:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> $DIR/rename.rs:103:9
+  --> $DIR/rename.rs:107:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:104:9
+  --> $DIR/rename.rs:108:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:105:9
+  --> $DIR/rename.rs:109:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 54 previous errors
+error: aborting due to 56 previous errors
 
diff --git a/tests/ui/result_large_err.rs b/tests/ui/result_large_err.rs
index 14a1f7e1db5..b25348bf996 100644
--- a/tests/ui/result_large_err.rs
+++ b/tests/ui/result_large_err.rs
@@ -1,3 +1,5 @@
+//@ignore-32bit
+
 #![warn(clippy::result_large_err)]
 #![allow(clippy::large_enum_variant)]
 
diff --git a/tests/ui/result_large_err.stderr b/tests/ui/result_large_err.stderr
index d42dd6600a3..6602f396a9c 100644
--- a/tests/ui/result_large_err.stderr
+++ b/tests/ui/result_large_err.stderr
@@ -1,5 +1,5 @@
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:8:23
+  --> $DIR/result_large_err.rs:10:23
    |
 LL | pub fn large_err() -> Result<(), [u8; 512]> {
    |                       ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -9,7 +9,7 @@ LL | pub fn large_err() -> Result<(), [u8; 512]> {
    = help: to override `-D warnings` add `#[allow(clippy::result_large_err)]`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:20:21
+  --> $DIR/result_large_err.rs:22:21
    |
 LL |     pub fn ret() -> Result<(), Self> {
    |                     ^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes
@@ -17,7 +17,7 @@ LL |     pub fn ret() -> Result<(), Self> {
    = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:26:26
+  --> $DIR/result_large_err.rs:28:26
    |
 LL | pub fn struct_error() -> Result<(), FullyDefinedLargeError> {
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes
@@ -25,7 +25,7 @@ LL | pub fn struct_error() -> Result<(), FullyDefinedLargeError> {
    = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:32:45
+  --> $DIR/result_large_err.rs:34:45
    |
 LL | pub fn large_err_via_type_alias<T>(x: T) -> Fdlr<T> {
    |                                             ^^^^^^^ the `Err`-variant is at least 240 bytes
@@ -33,7 +33,7 @@ LL | pub fn large_err_via_type_alias<T>(x: T) -> Fdlr<T> {
    = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:41:34
+  --> $DIR/result_large_err.rs:43:34
    |
 LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeError)> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 256 bytes
@@ -41,7 +41,7 @@ LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeErro
    = help: try reducing the size of `(u128, R, FullyDefinedLargeError)`, for example by boxing large elements or replacing it with `Box<(u128, R, FullyDefinedLargeError)>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:53:34
+  --> $DIR/result_large_err.rs:55:34
    |
 LL |     _Omg([u8; 512]),
    |     --------------- the largest variant contains at least 512 bytes
@@ -52,7 +52,7 @@ LL |     pub fn large_enum_error() -> Result<(), Self> {
    = help: try reducing the size of `LargeErrorVariants<()>`, for example by boxing large elements or replacing it with `Box<LargeErrorVariants<()>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:66:30
+  --> $DIR/result_large_err.rs:68:30
    |
 LL |     _Biggest([u8; 1024]),
    |     -------------------- the largest variant contains at least 1024 bytes
@@ -65,7 +65,7 @@ LL |     fn large_enum_error() -> Result<(), Self> {
    = help: try reducing the size of `MultipleLargeVariants`, for example by boxing large elements or replacing it with `Box<MultipleLargeVariants>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:73:25
+  --> $DIR/result_large_err.rs:75:25
    |
 LL |     fn large_error() -> Result<(), [u8; 512]> {
    |                         ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -73,7 +73,7 @@ LL |     fn large_error() -> Result<(), [u8; 512]> {
    = help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:93:29
+  --> $DIR/result_large_err.rs:95:29
    |
 LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> {
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -81,7 +81,7 @@ LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> {
    = help: try reducing the size of `FullyDefinedUnionError`, for example by boxing large elements or replacing it with `Box<FullyDefinedUnionError>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:103:40
+  --> $DIR/result_large_err.rs:105:40
    |
 LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -89,7 +89,7 @@ LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
    = help: try reducing the size of `UnionError<T>`, for example by boxing large elements or replacing it with `Box<UnionError<T>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:113:34
+  --> $DIR/result_large_err.rs:115:34
    |
 LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes
@@ -97,7 +97,7 @@ LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> {
    = help: try reducing the size of `ArrayError<i32, U>`, for example by boxing large elements or replacing it with `Box<ArrayError<i32, U>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:118:31
+  --> $DIR/result_large_err.rs:120:31
    |
 LL | pub fn array_error<T, U>() -> Result<(), ArrayError<(i32, T), U>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes
diff --git a/tests/ui/similar_names.rs b/tests/ui/similar_names.rs
index c5a941316da..f46af56c6e2 100644
--- a/tests/ui/similar_names.rs
+++ b/tests/ui/similar_names.rs
@@ -3,6 +3,7 @@
     unused,
     clippy::println_empty_string,
     clippy::empty_loop,
+    clippy::never_loop,
     clippy::diverging_sub_expression,
     clippy::let_unit_value
 )]
diff --git a/tests/ui/similar_names.stderr b/tests/ui/similar_names.stderr
index 011dbe679c0..44ae3532a48 100644
--- a/tests/ui/similar_names.stderr
+++ b/tests/ui/similar_names.stderr
@@ -1,11 +1,11 @@
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:21:9
+  --> $DIR/similar_names.rs:22:9
    |
 LL |     let bpple: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:19:9
+  --> $DIR/similar_names.rs:20:9
    |
 LL |     let apple: i32;
    |         ^^^^^
@@ -13,73 +13,73 @@ LL |     let apple: i32;
    = help: to override `-D warnings` add `#[allow(clippy::similar_names)]`
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:24:9
+  --> $DIR/similar_names.rs:25:9
    |
 LL |     let cpple: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:19:9
+  --> $DIR/similar_names.rs:20:9
    |
 LL |     let apple: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:49:9
+  --> $DIR/similar_names.rs:50:9
    |
 LL |     let bluby: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:48:9
+  --> $DIR/similar_names.rs:49:9
    |
 LL |     let blubx: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:54:9
+  --> $DIR/similar_names.rs:55:9
    |
 LL |     let coke: i32;
    |         ^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:52:9
+  --> $DIR/similar_names.rs:53:9
    |
 LL |     let cake: i32;
    |         ^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:73:9
+  --> $DIR/similar_names.rs:74:9
    |
 LL |     let xyzeabc: i32;
    |         ^^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:71:9
+  --> $DIR/similar_names.rs:72:9
    |
 LL |     let xyz1abc: i32;
    |         ^^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:78:9
+  --> $DIR/similar_names.rs:79:9
    |
 LL |     let parsee: i32;
    |         ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:76:9
+  --> $DIR/similar_names.rs:77:9
    |
 LL |     let parser: i32;
    |         ^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:100:16
+  --> $DIR/similar_names.rs:101:16
    |
 LL |         bpple: sprang,
    |                ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:99:16
+  --> $DIR/similar_names.rs:100:16
    |
 LL |         apple: spring,
    |                ^^^^^^
diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs
index d6493f23413..3cc8061647d 100644
--- a/tests/ui/single_call_fn.rs
+++ b/tests/ui/single_call_fn.rs
@@ -1,3 +1,4 @@
+//@ignore-32bit
 //@aux-build:proc_macros.rs
 #![allow(clippy::redundant_closure_call, unused)]
 #![warn(clippy::single_call_fn)]
diff --git a/tests/ui/single_call_fn.stderr b/tests/ui/single_call_fn.stderr
index 4acb383c408..d5cd707754c 100644
--- a/tests/ui/single_call_fn.stderr
+++ b/tests/ui/single_call_fn.stderr
@@ -1,5 +1,5 @@
 error: this function is only used once
-  --> $DIR/single_call_fn.rs:33:1
+  --> $DIR/single_call_fn.rs:34:1
    |
 LL | / fn c() {
 LL | |     println!("really");
@@ -9,7 +9,7 @@ LL | | }
    | |_^
    |
 help: used here
-  --> $DIR/single_call_fn.rs:40:5
+  --> $DIR/single_call_fn.rs:41:5
    |
 LL |     c();
    |     ^
@@ -17,37 +17,37 @@ LL |     c();
    = help: to override `-D warnings` add `#[allow(clippy::single_call_fn)]`
 
 error: this function is only used once
-  --> $DIR/single_call_fn.rs:12:1
+  --> $DIR/single_call_fn.rs:13:1
    |
 LL | fn i() {}
    | ^^^^^^^^^
    |
 help: used here
-  --> $DIR/single_call_fn.rs:17:13
+  --> $DIR/single_call_fn.rs:18:13
    |
 LL |     let a = i;
    |             ^
 
 error: this function is only used once
-  --> $DIR/single_call_fn.rs:43:1
+  --> $DIR/single_call_fn.rs:44:1
    |
 LL | fn a() {}
    | ^^^^^^^^^
    |
 help: used here
-  --> $DIR/single_call_fn.rs:46:5
+  --> $DIR/single_call_fn.rs:47:5
    |
 LL |     a();
    |     ^
 
 error: this function is only used once
-  --> $DIR/single_call_fn.rs:13:1
+  --> $DIR/single_call_fn.rs:14:1
    |
 LL | fn j() {}
    | ^^^^^^^^^
    |
 help: used here
-  --> $DIR/single_call_fn.rs:24:9
+  --> $DIR/single_call_fn.rs:25:9
    |
 LL |         j();
    |         ^
diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs
index f8d85ed38cd..5c3086c9d69 100644
--- a/tests/ui/slow_vector_initialization.rs
+++ b/tests/ui/slow_vector_initialization.rs
@@ -1,5 +1,5 @@
-use std::iter::repeat;
 //@no-rustfix
+use std::iter::repeat;
 fn main() {
     resize_vector();
     extend_vector();
@@ -86,6 +86,20 @@ fn from_empty_vec() {
     vec1 = Vec::new();
     vec1.resize(10, 0);
     //~^ ERROR: slow zero-filling initialization
+
+    vec1 = vec![];
+    vec1.resize(10, 0);
+    //~^ ERROR: slow zero-filling initialization
+
+    macro_rules! x {
+        () => {
+            vec![]
+        };
+    }
+
+    // `vec![]` comes from another macro, don't warn
+    vec1 = x!();
+    vec1.resize(10, 0);
 }
 
 fn do_stuff(vec: &mut [u8]) {}
diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr
index f4501551656..4d24400ecb5 100644
--- a/tests/ui/slow_vector_initialization.stderr
+++ b/tests/ui/slow_vector_initialization.stderr
@@ -97,8 +97,16 @@ LL |     vec1 = Vec::new();
 LL |     vec1.resize(10, 0);
    |     ^^^^^^^^^^^^^^^^^^
 
+error: slow zero-filling initialization
+  --> $DIR/slow_vector_initialization.rs:91:5
+   |
+LL |     vec1 = vec![];
+   |            ------ help: consider replacing this with: `vec![0; 10]`
+LL |     vec1.resize(10, 0);
+   |     ^^^^^^^^^^^^^^^^^^
+
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/slow_vector_initialization.rs:91:18
+  --> $DIR/slow_vector_initialization.rs:105:18
    |
 LL | fn do_stuff(vec: &mut [u8]) {}
    |                  ^^^^^^^^^ help: consider changing to: `&[u8]`
@@ -106,5 +114,5 @@ LL | fn do_stuff(vec: &mut [u8]) {}
    = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui/std_instead_of_core.fixed b/tests/ui/std_instead_of_core.fixed
new file mode 100644
index 00000000000..8027c053fb5
--- /dev/null
+++ b/tests/ui/std_instead_of_core.fixed
@@ -0,0 +1,62 @@
+#![warn(clippy::std_instead_of_core)]
+#![allow(unused_imports)]
+
+extern crate alloc;
+
+#[warn(clippy::std_instead_of_core)]
+fn std_instead_of_core() {
+    // Regular import
+    use core::hash::Hasher;
+    //~^ ERROR: used import from `std` instead of `core`
+    // Absolute path
+    use ::core::hash::Hash;
+    //~^ ERROR: used import from `std` instead of `core`
+    // Don't lint on `env` macro
+    use std::env;
+
+    // Multiple imports
+    use core::fmt::{Debug, Result};
+    //~^ ERROR: used import from `std` instead of `core`
+
+    // Function calls
+    let ptr = core::ptr::null::<u32>();
+    //~^ ERROR: used import from `std` instead of `core`
+    let ptr_mut = ::core::ptr::null_mut::<usize>();
+    //~^ ERROR: used import from `std` instead of `core`
+
+    // Types
+    let cell = core::cell::Cell::new(8u32);
+    //~^ ERROR: used import from `std` instead of `core`
+    let cell_absolute = ::core::cell::Cell::new(8u32);
+    //~^ ERROR: used import from `std` instead of `core`
+
+    let _ = std::env!("PATH");
+
+    // do not lint until `error_in_core` is stable
+    use std::error::Error;
+
+    // lint items re-exported from private modules, `core::iter::traits::iterator::Iterator`
+    use core::iter::Iterator;
+    //~^ ERROR: used import from `std` instead of `core`
+}
+
+#[warn(clippy::std_instead_of_alloc)]
+fn std_instead_of_alloc() {
+    // Only lint once.
+    use alloc::vec;
+    //~^ ERROR: used import from `std` instead of `alloc`
+    use alloc::vec::Vec;
+    //~^ ERROR: used import from `std` instead of `alloc`
+}
+
+#[warn(clippy::alloc_instead_of_core)]
+fn alloc_instead_of_core() {
+    use core::slice::from_ref;
+    //~^ ERROR: used import from `alloc` instead of `core`
+}
+
+fn main() {
+    std_instead_of_core();
+    std_instead_of_alloc();
+    alloc_instead_of_core();
+}
diff --git a/tests/ui/std_instead_of_core.rs b/tests/ui/std_instead_of_core.rs
index 2e44487d77e..63a096384d7 100644
--- a/tests/ui/std_instead_of_core.rs
+++ b/tests/ui/std_instead_of_core.rs
@@ -17,7 +17,6 @@ fn std_instead_of_core() {
     // Multiple imports
     use std::fmt::{Debug, Result};
     //~^ ERROR: used import from `std` instead of `core`
-    //~| ERROR: used import from `std` instead of `core`
 
     // Function calls
     let ptr = std::ptr::null::<u32>();
diff --git a/tests/ui/std_instead_of_core.stderr b/tests/ui/std_instead_of_core.stderr
index 7435d716157..ca26f77bd37 100644
--- a/tests/ui/std_instead_of_core.stderr
+++ b/tests/ui/std_instead_of_core.stderr
@@ -2,103 +2,76 @@ error: used import from `std` instead of `core`
   --> $DIR/std_instead_of_core.rs:9:9
    |
 LL |     use std::hash::Hasher;
-   |         ^^^^^^^^^^^^^^^^^
+   |         ^^^ help: consider importing the item from `core`: `core`
    |
-   = help: consider importing the item from `core`
    = note: `-D clippy::std-instead-of-core` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:12:9
+  --> $DIR/std_instead_of_core.rs:12:11
    |
 LL |     use ::std::hash::Hash;
-   |         ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider importing the item from `core`
+   |           ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:18:20
+  --> $DIR/std_instead_of_core.rs:18:9
    |
 LL |     use std::fmt::{Debug, Result};
-   |                    ^^^^^
-   |
-   = help: consider importing the item from `core`
+   |         ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:18:27
-   |
-LL |     use std::fmt::{Debug, Result};
-   |                           ^^^^^^
-   |
-   = help: consider importing the item from `core`
-
-error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:23:15
+  --> $DIR/std_instead_of_core.rs:22:15
    |
 LL |     let ptr = std::ptr::null::<u32>();
-   |               ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider importing the item from `core`
+   |               ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:25:19
+  --> $DIR/std_instead_of_core.rs:24:21
    |
 LL |     let ptr_mut = ::std::ptr::null_mut::<usize>();
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider importing the item from `core`
+   |                     ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:29:16
+  --> $DIR/std_instead_of_core.rs:28:16
    |
 LL |     let cell = std::cell::Cell::new(8u32);
-   |                ^^^^^^^^^^^^^^^
-   |
-   = help: consider importing the item from `core`
+   |                ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:31:25
+  --> $DIR/std_instead_of_core.rs:30:27
    |
 LL |     let cell_absolute = ::std::cell::Cell::new(8u32);
-   |                         ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider importing the item from `core`
+   |                           ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:40:9
+  --> $DIR/std_instead_of_core.rs:39:9
    |
 LL |     use std::iter::Iterator;
-   |         ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider importing the item from `core`
+   |         ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `alloc`
-  --> $DIR/std_instead_of_core.rs:47:9
+  --> $DIR/std_instead_of_core.rs:46:9
    |
 LL |     use std::vec;
-   |         ^^^^^^^^
+   |         ^^^ help: consider importing the item from `alloc`: `alloc`
    |
-   = help: consider importing the item from `alloc`
    = note: `-D clippy::std-instead-of-alloc` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]`
 
 error: used import from `std` instead of `alloc`
-  --> $DIR/std_instead_of_core.rs:49:9
+  --> $DIR/std_instead_of_core.rs:48:9
    |
 LL |     use std::vec::Vec;
-   |         ^^^^^^^^^^^^^
-   |
-   = help: consider importing the item from `alloc`
+   |         ^^^ help: consider importing the item from `alloc`: `alloc`
 
 error: used import from `alloc` instead of `core`
-  --> $DIR/std_instead_of_core.rs:55:9
+  --> $DIR/std_instead_of_core.rs:54:9
    |
 LL |     use alloc::slice::from_ref;
-   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^ help: consider importing the item from `core`: `core`
    |
-   = help: consider importing the item from `core`
    = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]`
 
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/transmute_32bit.stderr b/tests/ui/transmute_32bit.stderr
index 75ddca60d2a..baa819e30fd 100644
--- a/tests/ui/transmute_32bit.stderr
+++ b/tests/ui/transmute_32bit.stderr
@@ -1,39 +1,29 @@
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+error: transmute from a `f32` to a pointer
   --> $DIR/transmute_32bit.rs:6:31
    |
 LL |         let _: *const usize = std::mem::transmute(6.0f32);
-   |                               ^^^^^^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `f32` (32 bits)
-   = note: target type: `*const usize` (64 bits)
+   = note: `-D clippy::wrong-transmute` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::wrong_transmute)]`
 
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+error: transmute from a `f32` to a pointer
   --> $DIR/transmute_32bit.rs:8:29
    |
 LL |         let _: *mut usize = std::mem::transmute(6.0f32);
-   |                             ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: source type: `f32` (32 bits)
-   = note: target type: `*mut usize` (64 bits)
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+error: transmute from a `char` to a pointer
   --> $DIR/transmute_32bit.rs:10:31
    |
 LL |         let _: *const usize = std::mem::transmute('x');
-   |                               ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: source type: `char` (32 bits)
-   = note: target type: `*const usize` (64 bits)
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+error: transmute from a `char` to a pointer
   --> $DIR/transmute_32bit.rs:12:29
    |
 LL |         let _: *mut usize = std::mem::transmute('x');
-   |                             ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: source type: `char` (32 bits)
-   = note: target type: `*mut usize` (64 bits)
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/unnecessary_struct_initialization.fixed b/tests/ui/unnecessary_struct_initialization.fixed
index b5dedef5f4c..f3cf65da2d6 100644
--- a/tests/ui/unnecessary_struct_initialization.fixed
+++ b/tests/ui/unnecessary_struct_initialization.fixed
@@ -1,4 +1,4 @@
-#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)]
+#![allow(clippy::non_canonical_clone_impl, unused)]
 #![warn(clippy::unnecessary_struct_initialization)]
 
 struct S {
diff --git a/tests/ui/unnecessary_struct_initialization.rs b/tests/ui/unnecessary_struct_initialization.rs
index 2222c3ddf37..bd5302f9d85 100644
--- a/tests/ui/unnecessary_struct_initialization.rs
+++ b/tests/ui/unnecessary_struct_initialization.rs
@@ -1,4 +1,4 @@
-#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)]
+#![allow(clippy::non_canonical_clone_impl, unused)]
 #![warn(clippy::unnecessary_struct_initialization)]
 
 struct S {
diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed
index 3ff2acbe28f..bcbca971a78 100644
--- a/tests/ui/vec.fixed
+++ b/tests/ui/vec.fixed
@@ -120,6 +120,7 @@ fn issue11075() {
             stringify!($e)
         };
     }
+    #[allow(clippy::never_loop)]
     for _string in [repro!(true), repro!(null)] {
         unimplemented!();
     }
diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs
index 2ab025f424a..087425585de 100644
--- a/tests/ui/vec.rs
+++ b/tests/ui/vec.rs
@@ -120,6 +120,7 @@ fn issue11075() {
             stringify!($e)
         };
     }
+    #[allow(clippy::never_loop)]
     for _string in vec![repro!(true), repro!(null)] {
         unimplemented!();
     }
diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr
index a28024d236a..fc261838fe3 100644
--- a/tests/ui/vec.stderr
+++ b/tests/ui/vec.stderr
@@ -86,31 +86,31 @@ LL |     for _ in vec![1, 2, 3] {}
    |              ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:123:20
+  --> $DIR/vec.rs:124:20
    |
 LL |     for _string in vec![repro!(true), repro!(null)] {
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[repro!(true), repro!(null)]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:140:18
+  --> $DIR/vec.rs:141:18
    |
 LL |     in_macro!(1, vec![1, 2], vec![1; 2]);
    |                  ^^^^^^^^^^ help: you can use an array directly: `[1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:140:30
+  --> $DIR/vec.rs:141:30
    |
 LL |     in_macro!(1, vec![1, 2], vec![1; 2]);
    |                              ^^^^^^^^^^ help: you can use an array directly: `[1; 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:159:14
+  --> $DIR/vec.rs:160:14
    |
 LL |     for a in vec![1, 2, 3] {
    |              ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:163:14
+  --> $DIR/vec.rs:164:14
    |
 LL |     for a in vec![String::new(), String::new()] {
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]`
diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr
index fc24dba4543..6d382a267ad 100644
--- a/tests/ui/write_literal_2.stderr
+++ b/tests/ui/write_literal_2.stderr
@@ -2,7 +2,9 @@ error: unnecessary raw string literal
   --> $DIR/write_literal_2.rs:13:24
    |
 LL |     writeln!(v, r"{}", r"{hello}");
-   |                        ^^^^^^^^^^ help: try: `"{hello}"`
+   |                        -^^^^^^^^^
+   |                        |
+   |                        help: use a string literal instead: `"{hello}"`
    |
    = note: `-D clippy::needless-raw-strings` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::needless_raw_strings)]`