about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-11-22 17:09:06 +0000
committerbors <bors@rust-lang.org>2022-11-22 17:09:06 +0000
commitb33afd61edfb690ace17d0672b367e44758c1bef (patch)
tree4b806322d7fb1463672319546e1aadc3e2a0b5cc /tests
parent9e093072457d9cafe8a7259992d1a05d179e4757 (diff)
parente95d40980b3044a6a9cad1b5e72eb57390790d18 (diff)
downloadrust-b33afd61edfb690ace17d0672b367e44758c1bef.tar.gz
rust-b33afd61edfb690ace17d0672b367e44758c1bef.zip
Auto merge of #104688 - flip1995:clippyup, r=Manishearth,flip1995
Update Clippy

r? `@Manishearth`

Sorry for taking so long. There were so many blockers and so little time. This situation should be mitigated with #104007 in the future.
Diffstat (limited to 'tests')
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr8
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr8
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr8
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr8
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr8
-rw-r--r--tests/ui-internal/custom_ice_message.rs1
-rw-r--r--tests/ui-internal/custom_ice_message.stderr2
-rw-r--r--tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr18
-rw-r--r--tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs11
-rw-r--r--tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr4
-rw-r--r--tests/ui-toml/expect_used/expect_used.rs23
-rw-r--r--tests/ui-toml/expect_used/expect_used.stderr4
-rw-r--r--tests/ui-toml/mut_key/clippy.toml1
-rw-r--r--tests/ui-toml/mut_key/mut_key.rs53
-rw-r--r--tests/ui-toml/print_macro/clippy.toml1
-rw-r--r--tests/ui-toml/print_macro/print_macro.rs20
-rw-r--r--tests/ui-toml/print_macro/print_macro.stderr18
-rw-r--r--tests/ui-toml/toml_disallowed_methods/clippy.toml6
-rw-r--r--tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs30
-rw-r--r--tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr50
-rw-r--r--tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr3
-rw-r--r--tests/ui-toml/unwrap_used/unwrap_used.rs21
-rw-r--r--tests/ui-toml/unwrap_used/unwrap_used.stderr32
-rw-r--r--tests/ui-toml/vec_box_sized/test.rs5
-rw-r--r--tests/ui-toml/vec_box_sized/test.stderr6
-rw-r--r--tests/ui/arithmetic_side_effects.rs8
-rw-r--r--tests/ui/arithmetic_side_effects.stderr110
-rw-r--r--tests/ui/auxiliary/doc_unsafe_macros.rs8
-rw-r--r--tests/ui/blanket_clippy_restriction_lints.rs2
-rw-r--r--tests/ui/blanket_clippy_restriction_lints.stderr27
-rw-r--r--tests/ui/bool_to_int_with_if.fixed22
-rw-r--r--tests/ui/bool_to_int_with_if.rs22
-rw-r--r--tests/ui/bool_to_int_with_if.stderr18
-rw-r--r--tests/ui/cognitive_complexity.rs16
-rw-r--r--tests/ui/cognitive_complexity.stderr18
-rw-r--r--tests/ui/crashes/ice-2774.stderr2
-rw-r--r--tests/ui/crashes/ice-9746.rs15
-rw-r--r--tests/ui/crashes/needless_lifetimes_impl_trait.stderr2
-rw-r--r--tests/ui/crate_level_checks/no_std_main_recursion.rs1
-rw-r--r--tests/ui/doc_errors.stderr36
-rw-r--r--tests/ui/doc_unnecessary_unsafe.rs148
-rw-r--r--tests/ui/doc_unnecessary_unsafe.stderr51
-rw-r--r--tests/ui/doc_unsafe.stderr34
-rw-r--r--tests/ui/eq_op.rs1
-rw-r--r--tests/ui/eq_op.stderr56
-rw-r--r--tests/ui/equatable_if_let.fixed11
-rw-r--r--tests/ui/equatable_if_let.rs7
-rw-r--r--tests/ui/equatable_if_let.stderr42
-rw-r--r--tests/ui/expect.stderr6
-rw-r--r--tests/ui/explicit_auto_deref.fixed11
-rw-r--r--tests/ui/explicit_auto_deref.rs11
-rw-r--r--tests/ui/fn_params_excessive_bools.rs8
-rw-r--r--tests/ui/fn_params_excessive_bools.stderr22
-rw-r--r--tests/ui/from_raw_with_void_ptr.rs34
-rw-r--r--tests/ui/from_raw_with_void_ptr.stderr63
-rw-r--r--tests/ui/get_unwrap.stderr26
-rw-r--r--tests/ui/infallible_destructuring_match.fixed12
-rw-r--r--tests/ui/infallible_destructuring_match.rs14
-rw-r--r--tests/ui/infallible_destructuring_match.stderr16
-rw-r--r--tests/ui/issue_4266.stderr4
-rw-r--r--tests/ui/let_underscore_drop.rs28
-rw-r--r--tests/ui/let_underscore_drop.stderr27
-rw-r--r--tests/ui/let_underscore_future.rs20
-rw-r--r--tests/ui/let_underscore_future.stderr27
-rw-r--r--tests/ui/let_underscore_lock.rs31
-rw-r--r--tests/ui/let_underscore_lock.stderr66
-rw-r--r--tests/ui/let_underscore_must_use.stderr24
-rw-r--r--tests/ui/manual_flatten.rs2
-rw-r--r--tests/ui/manual_instant_elapsed.fixed1
-rw-r--r--tests/ui/manual_instant_elapsed.rs1
-rw-r--r--tests/ui/manual_instant_elapsed.stderr4
-rw-r--r--tests/ui/manual_is_ascii_check.fixed45
-rw-r--r--tests/ui/manual_is_ascii_check.rs45
-rw-r--r--tests/ui/manual_is_ascii_check.stderr70
-rw-r--r--tests/ui/manual_let_else.rs237
-rw-r--r--tests/ui/manual_let_else.stderr263
-rw-r--r--tests/ui/manual_let_else_match.rs121
-rw-r--r--tests/ui/manual_let_else_match.stderr58
-rw-r--r--tests/ui/manual_ok_or.fixed1
-rw-r--r--tests/ui/manual_ok_or.rs1
-rw-r--r--tests/ui/manual_ok_or.stderr8
-rw-r--r--tests/ui/map_flatten_fixable.fixed1
-rw-r--r--tests/ui/map_flatten_fixable.rs1
-rw-r--r--tests/ui/map_flatten_fixable.stderr18
-rw-r--r--tests/ui/match_expr_like_matches_macro.fixed7
-rw-r--r--tests/ui/match_expr_like_matches_macro.rs7
-rw-r--r--tests/ui/match_expr_like_matches_macro.stderr28
-rw-r--r--tests/ui/missing_panics_doc.stderr49
-rw-r--r--tests/ui/mut_from_ref.rs2
-rw-r--r--tests/ui/mut_mut.rs17
-rw-r--r--tests/ui/mut_range_bound.rs2
-rw-r--r--tests/ui/mut_range_bound.stderr2
-rw-r--r--tests/ui/needless_borrow.fixed125
-rw-r--r--tests/ui/needless_borrow.rs125
-rw-r--r--tests/ui/needless_borrow.stderr8
-rw-r--r--tests/ui/needless_borrowed_ref.fixed67
-rw-r--r--tests/ui/needless_borrowed_ref.rs67
-rw-r--r--tests/ui/needless_borrowed_ref.stderr113
-rw-r--r--tests/ui/needless_collect.fixed29
-rw-r--r--tests/ui/needless_collect.rs29
-rw-r--r--tests/ui/needless_collect.stderr26
-rw-r--r--tests/ui/needless_collect_indirect.rs1
-rw-r--r--tests/ui/needless_collect_indirect.stderr32
-rw-r--r--tests/ui/needless_lifetimes.rs96
-rw-r--r--tests/ui/needless_lifetimes.stderr246
-rw-r--r--tests/ui/never_loop.rs21
-rw-r--r--tests/ui/never_loop.stderr14
-rw-r--r--tests/ui/new_ret_no_self.rs50
-rw-r--r--tests/ui/new_ret_no_self.stderr18
-rw-r--r--tests/ui/option_if_let_else.fixed9
-rw-r--r--tests/ui/option_if_let_else.rs9
-rw-r--r--tests/ui/or_fun_call.fixed16
-rw-r--r--tests/ui/or_fun_call.rs16
-rw-r--r--tests/ui/or_fun_call.stderr14
-rw-r--r--tests/ui/question_mark.fixed3
-rw-r--r--tests/ui/question_mark.rs3
-rw-r--r--tests/ui/question_mark.stderr4
-rw-r--r--tests/ui/rename.fixed8
-rw-r--r--tests/ui/rename.rs8
-rw-r--r--tests/ui/rename.stderr106
-rw-r--r--tests/ui/result_large_err.rs12
-rw-r--r--tests/ui/result_large_err.stderr30
-rw-r--r--tests/ui/seek_from_current.fixed26
-rw-r--r--tests/ui/seek_from_current.rs26
-rw-r--r--tests/ui/seek_from_current.stderr10
-rw-r--r--tests/ui/seek_to_start_instead_of_rewind.fixed137
-rw-r--r--tests/ui/seek_to_start_instead_of_rewind.rs137
-rw-r--r--tests/ui/seek_to_start_instead_of_rewind.stderr22
-rw-r--r--tests/ui/single_component_path_imports.stderr12
-rw-r--r--tests/ui/single_component_path_imports_nested_first.stderr15
-rw-r--r--tests/ui/string_extend.fixed3
-rw-r--r--tests/ui/string_extend.rs3
-rw-r--r--tests/ui/string_extend.stderr8
-rw-r--r--tests/ui/suspicious_xor_used_as_pow.rs34
-rw-r--r--tests/ui/suspicious_xor_used_as_pow.stderr51
-rw-r--r--tests/ui/swap.fixed9
-rw-r--r--tests/ui/swap.rs9
-rw-r--r--tests/ui/transmute.rs2
-rw-r--r--tests/ui/trivially_copy_pass_by_ref.rs1
-rw-r--r--tests/ui/trivially_copy_pass_by_ref.stderr36
-rw-r--r--tests/ui/unchecked_duration_subtraction.fixed17
-rw-r--r--tests/ui/unchecked_duration_subtraction.rs17
-rw-r--r--tests/ui/unchecked_duration_subtraction.stderr28
-rw-r--r--tests/ui/undocumented_unsafe_blocks.rs19
-rw-r--r--tests/ui/undocumented_unsafe_blocks.stderr26
-rw-r--r--tests/ui/unnecessary_join.stderr4
-rw-r--r--tests/ui/unused_rounding.fixed5
-rw-r--r--tests/ui/unused_rounding.rs5
-rw-r--r--tests/ui/unused_rounding.stderr8
-rw-r--r--tests/ui/unused_unit.fixed7
-rw-r--r--tests/ui/unused_unit.rs7
-rw-r--r--tests/ui/unused_unit.stderr40
-rw-r--r--tests/ui/unwrap.stderr6
-rw-r--r--tests/ui/unwrap_expect_used.stderr12
-rw-r--r--tests/ui/unwrap_or.rs2
-rw-r--r--tests/ui/use_self_trait.fixed41
-rw-r--r--tests/ui/use_self_trait.rs39
-rw-r--r--tests/ui/use_self_trait.stderr14
-rw-r--r--tests/ui/useless_attribute.fixed21
-rw-r--r--tests/ui/useless_attribute.rs21
-rw-r--r--tests/ui/useless_attribute.stderr6
-rw-r--r--tests/versioncheck.rs15
162 files changed, 3917 insertions, 736 deletions
diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr
index 9a7d802dc6d..163f8bb35e7 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr
+++ b/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr
@@ -12,5 +12,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:7:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr
index a280e1bacdf..259d39b1252 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr
+++ b/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:7:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
index a280e1bacdf..259d39b1252 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
+++ b/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:7:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr
index a280e1bacdf..259d39b1252 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr
+++ b/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:7:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr
index 88f6e00922b..97e6c3d5a55 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr
+++ b/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary structure name repetition
+  --> $DIR/main.rs:12:9
+   |
+LL |         Foo
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui-internal/custom_ice_message.rs b/tests/ui-internal/custom_ice_message.rs
index 5057a018300..4be04f77f5b 100644
--- a/tests/ui-internal/custom_ice_message.rs
+++ b/tests/ui-internal/custom_ice_message.rs
@@ -2,6 +2,7 @@
 // normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo"
 // normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs"
 // normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
+// normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
 
 #![deny(clippy::internal)]
 #![allow(clippy::missing_clippy_version_attribute)]
diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr
index 07c5941013c..2ba5890660f 100644
--- a/tests/ui-internal/custom_ice_message.stderr
+++ b/tests/ui-internal/custom_ice_message.stderr
@@ -1,4 +1,4 @@
-thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
+thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: internal compiler error: unexpected panic
diff --git a/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index 2a240cc249b..8bfc060e991 100644
--- a/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -1,3 +1,12 @@
+error: hardcoded path to a language item
+  --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
+   |
+LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: convert all references to use `LangItem::DerefMut`
+   = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
+
 error: hardcoded path to a diagnostic item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
    |
@@ -5,7 +14,6 @@ LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: convert all references to use `sym::Deref`
-   = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
 
 error: hardcoded path to a diagnostic item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
@@ -15,13 +23,5 @@ LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref",
    |
    = help: convert all references to use `sym::deref_method`
 
-error: hardcoded path to a language item
-  --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
-   |
-LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: convert all references to use `LangItem::DerefMut`
-
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
index 1aed09b7c7b..e8a023ab176 100644
--- a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
+++ b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
@@ -1,6 +1,6 @@
 #![warn(clippy::arithmetic_side_effects)]
 
-use core::ops::Add;
+use core::ops::{Add, Neg};
 
 #[derive(Clone, Copy)]
 struct Point {
@@ -16,9 +16,18 @@ impl Add for Point {
     }
 }
 
+impl Neg for Point {
+    type Output = Self;
+
+    fn neg(self) -> Self::Output {
+        todo!()
+    }
+}
+
 fn main() {
     let _ = Point { x: 1, y: 0 } + Point { x: 2, y: 3 };
 
     let point: Point = Point { x: 1, y: 0 };
     let _ = point + point;
+    let _ = -point;
 }
diff --git a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
index 4c75998437f..825aa1487e7 100644
--- a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
+++ b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
@@ -4,7 +4,7 @@ error: `std::string::String` may not be held across an `await` point per `clippy
 LL |     let _x = String::from("hello");
    |         ^^
    |
-   = note: strings are bad
+   = note: strings are bad (from clippy.toml)
    = note: `-D clippy::await-holding-invalid-type` implied by `-D warnings`
 
 error: `std::net::Ipv4Addr` may not be held across an `await` point per `clippy.toml`
@@ -19,7 +19,7 @@ error: `std::string::String` may not be held across an `await` point per `clippy
 LL |         let _x = String::from("hi!");
    |             ^^
    |
-   = note: strings are bad
+   = note: strings are bad (from clippy.toml)
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui-toml/expect_used/expect_used.rs b/tests/ui-toml/expect_used/expect_used.rs
index 22dcd3ae9d6..bff97d97df7 100644
--- a/tests/ui-toml/expect_used/expect_used.rs
+++ b/tests/ui-toml/expect_used/expect_used.rs
@@ -16,14 +16,19 @@ fn main() {
     expect_result();
 }
 
-#[test]
-fn test_expect_option() {
-    let opt = Some(0);
-    let _ = opt.expect("");
-}
+#[cfg(test)]
+mod issue9612 {
+    // should not lint in `#[cfg(test)]` modules
+    #[test]
+    fn test_fn() {
+        let _a: u8 = 2.try_into().unwrap();
+        let _a: u8 = 3.try_into().expect("");
 
-#[test]
-fn test_expect_result() {
-    let res: Result<u8, ()> = Ok(0);
-    let _ = res.expect("");
+        util();
+    }
+
+    fn util() {
+        let _a: u8 = 4.try_into().unwrap();
+        let _a: u8 = 5.try_into().expect("");
+    }
 }
diff --git a/tests/ui-toml/expect_used/expect_used.stderr b/tests/ui-toml/expect_used/expect_used.stderr
index 28a08599c67..1e9bb48c333 100644
--- a/tests/ui-toml/expect_used/expect_used.stderr
+++ b/tests/ui-toml/expect_used/expect_used.stderr
@@ -1,4 +1,4 @@
-error: used `expect()` on `an Option` value
+error: used `expect()` on an `Option` value
   --> $DIR/expect_used.rs:6:13
    |
 LL |     let _ = opt.expect("");
@@ -7,7 +7,7 @@ LL |     let _ = opt.expect("");
    = help: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
-error: used `expect()` on `a Result` value
+error: used `expect()` on a `Result` value
   --> $DIR/expect_used.rs:11:13
    |
 LL |     let _ = res.expect("");
diff --git a/tests/ui-toml/mut_key/clippy.toml b/tests/ui-toml/mut_key/clippy.toml
new file mode 100644
index 00000000000..6d33e192ee8
--- /dev/null
+++ b/tests/ui-toml/mut_key/clippy.toml
@@ -0,0 +1 @@
+ignore-interior-mutability = ["mut_key::Counted"]
\ No newline at end of file
diff --git a/tests/ui-toml/mut_key/mut_key.rs b/tests/ui-toml/mut_key/mut_key.rs
new file mode 100644
index 00000000000..667c51cb4a3
--- /dev/null
+++ b/tests/ui-toml/mut_key/mut_key.rs
@@ -0,0 +1,53 @@
+// compile-flags: --crate-name mut_key
+
+#![warn(clippy::mutable_key_type)]
+
+use std::cmp::{Eq, PartialEq};
+use std::collections::{HashMap, HashSet};
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+struct Counted<T> {
+    count: AtomicUsize,
+    val: T,
+}
+
+impl<T: Clone> Clone for Counted<T> {
+    fn clone(&self) -> Self {
+        Self {
+            count: AtomicUsize::new(0),
+            val: self.val.clone(),
+        }
+    }
+}
+
+impl<T: PartialEq> PartialEq for Counted<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.val == other.val
+    }
+}
+impl<T: PartialEq + Eq> Eq for Counted<T> {}
+
+impl<T: Hash> Hash for Counted<T> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.val.hash(state);
+    }
+}
+
+impl<T> Deref for Counted<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        self.count.fetch_add(1, Ordering::AcqRel);
+        &self.val
+    }
+}
+
+// This is not linted because `"mut_key::Counted"` is in
+// `arc_like_types` in `clippy.toml`
+fn should_not_take_this_arg(_v: HashSet<Counted<String>>) {}
+
+fn main() {
+    should_not_take_this_arg(HashSet::new());
+}
diff --git a/tests/ui-toml/print_macro/clippy.toml b/tests/ui-toml/print_macro/clippy.toml
new file mode 100644
index 00000000000..40b1dda5b2e
--- /dev/null
+++ b/tests/ui-toml/print_macro/clippy.toml
@@ -0,0 +1 @@
+allow-print-in-tests = true
diff --git a/tests/ui-toml/print_macro/print_macro.rs b/tests/ui-toml/print_macro/print_macro.rs
new file mode 100644
index 00000000000..5aefb6a6b4d
--- /dev/null
+++ b/tests/ui-toml/print_macro/print_macro.rs
@@ -0,0 +1,20 @@
+// compile-flags: --test
+#![warn(clippy::print_stdout)]
+#![warn(clippy::print_stderr)]
+
+fn foo(n: u32) {
+    print!("{n}");
+    eprint!("{n}");
+}
+
+#[test]
+pub fn foo1() {
+    print!("{}", 1);
+    eprint!("{}", 1);
+}
+
+#[cfg(test)]
+fn foo3() {
+    print!("{}", 1);
+    eprint!("{}", 1);
+}
diff --git a/tests/ui-toml/print_macro/print_macro.stderr b/tests/ui-toml/print_macro/print_macro.stderr
new file mode 100644
index 00000000000..d4b1ae84fd7
--- /dev/null
+++ b/tests/ui-toml/print_macro/print_macro.stderr
@@ -0,0 +1,18 @@
+error: use of `print!`
+  --> $DIR/print_macro.rs:6:5
+   |
+LL |     print!("{n}");
+   |     ^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::print-stdout` implied by `-D warnings`
+
+error: use of `eprint!`
+  --> $DIR/print_macro.rs:7:5
+   |
+LL |     eprint!("{n}");
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::print-stderr` implied by `-D warnings`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui-toml/toml_disallowed_methods/clippy.toml b/tests/ui-toml/toml_disallowed_methods/clippy.toml
index 28774db625b..41dbd506847 100644
--- a/tests/ui-toml/toml_disallowed_methods/clippy.toml
+++ b/tests/ui-toml/toml_disallowed_methods/clippy.toml
@@ -8,4 +8,10 @@ disallowed-methods = [
     { path = "regex::Regex::is_match", reason = "no matching allowed" },
     # can use an inline table but omit reason
     { path = "regex::Regex::new" },
+    # local paths
+    "conf_disallowed_methods::local_fn",
+    "conf_disallowed_methods::local_mod::f",
+    "conf_disallowed_methods::Struct::method",
+    "conf_disallowed_methods::Trait::provided_method",
+    "conf_disallowed_methods::Trait::implemented_method",
 ]
diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
index b483f160028..2f3160c8338 100644
--- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
+++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
@@ -1,3 +1,5 @@
+// compile-flags: --crate-name conf_disallowed_methods
+
 #![warn(clippy::disallowed_methods)]
 
 extern crate futures;
@@ -6,6 +8,27 @@ extern crate regex;
 use futures::stream::{empty, select_all};
 use regex::Regex;
 
+fn local_fn() {}
+
+struct Struct;
+
+impl Struct {
+    fn method(&self) {}
+}
+
+trait Trait {
+    fn provided_method(&self) {}
+    fn implemented_method(&self);
+}
+
+impl Trait for Struct {
+    fn implemented_method(&self) {}
+}
+
+mod local_mod {
+    pub fn f() {}
+}
+
 fn main() {
     let re = Regex::new(r"ab.*c").unwrap();
     re.is_match("abc");
@@ -26,4 +49,11 @@ fn main() {
 
     // resolve ambiguity between `futures::stream::select_all` the module and the function
     let same_name_as_module = select_all(vec![empty::<()>()]);
+
+    local_fn();
+    local_mod::f();
+    let s = Struct;
+    s.method();
+    s.provided_method();
+    s.implemented_method();
 }
diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
index 6d78c32e127..148d1cae51f 100644
--- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
+++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
@@ -1,5 +1,5 @@
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:10:14
+  --> $DIR/conf_disallowed_methods.rs:33:14
    |
 LL |     let re = Regex::new(r"ab.*c").unwrap();
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     let re = Regex::new(r"ab.*c").unwrap();
    = note: `-D clippy::disallowed-methods` implied by `-D warnings`
 
 error: use of a disallowed method `regex::Regex::is_match`
-  --> $DIR/conf_disallowed_methods.rs:11:5
+  --> $DIR/conf_disallowed_methods.rs:34:5
    |
 LL |     re.is_match("abc");
    |     ^^^^^^^^^^^^^^^^^^
@@ -15,46 +15,76 @@ LL |     re.is_match("abc");
    = note: no matching allowed (from clippy.toml)
 
 error: use of a disallowed method `std::iter::Iterator::sum`
-  --> $DIR/conf_disallowed_methods.rs:14:5
+  --> $DIR/conf_disallowed_methods.rs:37:5
    |
 LL |     a.iter().sum::<i32>();
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `slice::sort_unstable`
-  --> $DIR/conf_disallowed_methods.rs:16:5
+  --> $DIR/conf_disallowed_methods.rs:39:5
    |
 LL |     a.sort_unstable();
    |     ^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `f32::clamp`
-  --> $DIR/conf_disallowed_methods.rs:18:13
+  --> $DIR/conf_disallowed_methods.rs:41:13
    |
 LL |     let _ = 2.0f32.clamp(3.0f32, 4.0f32);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:21:61
+  --> $DIR/conf_disallowed_methods.rs:44:61
    |
 LL |     let indirect: fn(&str) -> Result<Regex, regex::Error> = Regex::new;
    |                                                             ^^^^^^^^^^
 
 error: use of a disallowed method `f32::clamp`
-  --> $DIR/conf_disallowed_methods.rs:24:28
+  --> $DIR/conf_disallowed_methods.rs:47:28
    |
 LL |     let in_call = Box::new(f32::clamp);
    |                            ^^^^^^^^^^
 
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:25:53
+  --> $DIR/conf_disallowed_methods.rs:48:53
    |
 LL |     let in_method_call = ["^", "$"].into_iter().map(Regex::new);
    |                                                     ^^^^^^^^^^
 
 error: use of a disallowed method `futures::stream::select_all`
-  --> $DIR/conf_disallowed_methods.rs:28:31
+  --> $DIR/conf_disallowed_methods.rs:51:31
    |
 LL |     let same_name_as_module = select_all(vec![empty::<()>()]);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: use of a disallowed method `conf_disallowed_methods::local_fn`
+  --> $DIR/conf_disallowed_methods.rs:53:5
+   |
+LL |     local_fn();
+   |     ^^^^^^^^^^
+
+error: use of a disallowed method `conf_disallowed_methods::local_mod::f`
+  --> $DIR/conf_disallowed_methods.rs:54:5
+   |
+LL |     local_mod::f();
+   |     ^^^^^^^^^^^^^^
+
+error: use of a disallowed method `conf_disallowed_methods::Struct::method`
+  --> $DIR/conf_disallowed_methods.rs:56:5
+   |
+LL |     s.method();
+   |     ^^^^^^^^^^
+
+error: use of a disallowed method `conf_disallowed_methods::Trait::provided_method`
+  --> $DIR/conf_disallowed_methods.rs:57:5
+   |
+LL |     s.provided_method();
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: use of a disallowed method `conf_disallowed_methods::Trait::implemented_method`
+  --> $DIR/conf_disallowed_methods.rs:58:5
+   |
+LL |     s.implemented_method();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 82ee8054132..f91d285c2e0 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -1,6 +1,7 @@
 error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of
            allow-dbg-in-tests
            allow-expect-in-tests
+           allow-print-in-tests
            allow-unwrap-in-tests
            allowed-scripts
            arithmetic-side-effects-allowed
@@ -20,8 +21,10 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
            enforced-import-renames
            enum-variant-name-threshold
            enum-variant-size-threshold
+           ignore-interior-mutability
            large-error-threshold
            literal-representation-threshold
+           matches-for-let-else
            max-fn-params-bools
            max-include-file-size
            max-struct-bools
diff --git a/tests/ui-toml/unwrap_used/unwrap_used.rs b/tests/ui-toml/unwrap_used/unwrap_used.rs
index 0e82fb20e45..bc8e8c1f070 100644
--- a/tests/ui-toml/unwrap_used/unwrap_used.rs
+++ b/tests/ui-toml/unwrap_used/unwrap_used.rs
@@ -66,8 +66,21 @@ fn main() {
     }
 }
 
-#[test]
-fn test() {
-    let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
-    let _ = boxed_slice.get(1).unwrap();
+#[cfg(test)]
+mod issue9612 {
+    // should not lint in `#[cfg(test)]` modules
+    #[test]
+    fn test_fn() {
+        let _a: u8 = 2.try_into().unwrap();
+        let _a: u8 = 3.try_into().expect("");
+
+        util();
+    }
+
+    fn util() {
+        let _a: u8 = 4.try_into().unwrap();
+        let _a: u8 = 5.try_into().expect("");
+        // should still warn
+        let _ = Box::new([0]).get(1).unwrap();
+    }
 }
diff --git a/tests/ui-toml/unwrap_used/unwrap_used.stderr b/tests/ui-toml/unwrap_used/unwrap_used.stderr
index 681b5eaf54d..94b5ef663ad 100644
--- a/tests/ui-toml/unwrap_used/unwrap_used.stderr
+++ b/tests/ui-toml/unwrap_used/unwrap_used.stderr
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(clippy::get_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:35:17
    |
 LL |         let _ = boxed_slice.get(1).unwrap();
@@ -25,7 +25,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:36:17
    |
 LL |         let _ = some_slice.get(0).unwrap();
@@ -39,7 +39,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:37:17
    |
 LL |         let _ = some_vec.get(0).unwrap();
@@ -53,7 +53,7 @@ error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:38:17
    |
 LL |         let _ = some_vecdeque.get(0).unwrap();
@@ -67,7 +67,7 @@ error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:39:17
    |
 LL |         let _ = some_hashmap.get(&1).unwrap();
@@ -81,7 +81,7 @@ error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:40:17
    |
 LL |         let _ = some_btreemap.get(&1).unwrap();
@@ -95,7 +95,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:44:22
    |
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
@@ -109,7 +109,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:49:10
    |
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
@@ -123,7 +123,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:50:10
    |
 LL |         *some_slice.get_mut(0).unwrap() = 1;
@@ -137,7 +137,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:51:10
    |
 LL |         *some_vec.get_mut(0).unwrap() = 1;
@@ -151,7 +151,7 @@ error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:52:10
    |
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
@@ -165,7 +165,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:64:17
    |
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
@@ -179,7 +179,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_used.rs:65:17
    |
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
@@ -188,10 +188,10 @@ LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:72:13
+  --> $DIR/unwrap_used.rs:84:17
    |
-LL |     let _ = boxed_slice.get(1).unwrap();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]`
+LL |         let _ = Box::new([0]).get(1).unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&Box::new([0])[1]`
 
 error: aborting due to 27 previous errors
 
diff --git a/tests/ui-toml/vec_box_sized/test.rs b/tests/ui-toml/vec_box_sized/test.rs
index bf04bee1637..4c46deb585b 100644
--- a/tests/ui-toml/vec_box_sized/test.rs
+++ b/tests/ui-toml/vec_box_sized/test.rs
@@ -7,8 +7,9 @@ struct C {
 }
 
 struct Foo(Vec<Box<u8>>);
-struct Bar(Vec<Box<u32>>);
-struct Baz(Vec<Box<(u32, u32)>>);
+struct Bar(Vec<Box<u16>>);
+struct Quux(Vec<Box<u32>>);
+struct Baz(Vec<Box<(u16, u16)>>);
 struct BarBaz(Vec<Box<S>>);
 struct FooBarBaz(Vec<Box<C>>);
 
diff --git a/tests/ui-toml/vec_box_sized/test.stderr b/tests/ui-toml/vec_box_sized/test.stderr
index cf194de3c55..55de68f8ecf 100644
--- a/tests/ui-toml/vec_box_sized/test.stderr
+++ b/tests/ui-toml/vec_box_sized/test.stderr
@@ -9,11 +9,11 @@ LL | struct Foo(Vec<Box<u8>>);
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
   --> $DIR/test.rs:10:12
    |
-LL | struct Bar(Vec<Box<u32>>);
-   |            ^^^^^^^^^^^^^ help: try: `Vec<u32>`
+LL | struct Bar(Vec<Box<u16>>);
+   |            ^^^^^^^^^^^^^ help: try: `Vec<u16>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/test.rs:13:18
+  --> $DIR/test.rs:14:18
    |
 LL | struct FooBarBaz(Vec<Box<C>>);
    |                  ^^^^^^^^^^^ help: try: `Vec<C>`
diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs
index b25e68f1306..b5ed8988a51 100644
--- a/tests/ui/arithmetic_side_effects.rs
+++ b/tests/ui/arithmetic_side_effects.rs
@@ -150,8 +150,12 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
     _n = 23 + 85;
 
     // Unary
-    _n = -1;
-    _n = -(-1);
+    _n = -2147483647;
+    _n = -i32::MAX;
+    _n = -i32::MIN;
+    _n = -&2147483647;
+    _n = -&i32::MAX;
+    _n = -&i32::MIN;
 }
 
 pub fn runtime_ops() {
diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr
index 0f06e22bae9..0259a0824e7 100644
--- a/tests/ui/arithmetic_side_effects.stderr
+++ b/tests/ui/arithmetic_side_effects.stderr
@@ -19,331 +19,331 @@ LL |     let _ = inferred_string + "";
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:161:5
+  --> $DIR/arithmetic_side_effects.rs:165:5
    |
 LL |     _n += 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:162:5
+  --> $DIR/arithmetic_side_effects.rs:166:5
    |
 LL |     _n += &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:163:5
+  --> $DIR/arithmetic_side_effects.rs:167:5
    |
 LL |     _n -= 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:164:5
+  --> $DIR/arithmetic_side_effects.rs:168:5
    |
 LL |     _n -= &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:165:5
+  --> $DIR/arithmetic_side_effects.rs:169:5
    |
 LL |     _n /= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:166:5
+  --> $DIR/arithmetic_side_effects.rs:170:5
    |
 LL |     _n /= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:167:5
+  --> $DIR/arithmetic_side_effects.rs:171:5
    |
 LL |     _n %= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:168:5
+  --> $DIR/arithmetic_side_effects.rs:172:5
    |
 LL |     _n %= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:169:5
+  --> $DIR/arithmetic_side_effects.rs:173:5
    |
 LL |     _n *= 2;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:170:5
+  --> $DIR/arithmetic_side_effects.rs:174:5
    |
 LL |     _n *= &2;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:173:10
+  --> $DIR/arithmetic_side_effects.rs:177:10
    |
 LL |     _n = _n + 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:174:10
+  --> $DIR/arithmetic_side_effects.rs:178:10
    |
 LL |     _n = _n + &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:175:10
+  --> $DIR/arithmetic_side_effects.rs:179:10
    |
 LL |     _n = 1 + _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:176:10
+  --> $DIR/arithmetic_side_effects.rs:180:10
    |
 LL |     _n = &1 + _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:177:10
+  --> $DIR/arithmetic_side_effects.rs:181:10
    |
 LL |     _n = _n - 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:178:10
+  --> $DIR/arithmetic_side_effects.rs:182:10
    |
 LL |     _n = _n - &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:179:10
+  --> $DIR/arithmetic_side_effects.rs:183:10
    |
 LL |     _n = 1 - _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:180:10
+  --> $DIR/arithmetic_side_effects.rs:184:10
    |
 LL |     _n = &1 - _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:181:10
+  --> $DIR/arithmetic_side_effects.rs:185:10
    |
 LL |     _n = _n / 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:182:10
+  --> $DIR/arithmetic_side_effects.rs:186:10
    |
 LL |     _n = _n / &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:183:10
+  --> $DIR/arithmetic_side_effects.rs:187:10
    |
 LL |     _n = _n % 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:184:10
+  --> $DIR/arithmetic_side_effects.rs:188:10
    |
 LL |     _n = _n % &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:185:10
+  --> $DIR/arithmetic_side_effects.rs:189:10
    |
 LL |     _n = _n * 2;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:186:10
+  --> $DIR/arithmetic_side_effects.rs:190:10
    |
 LL |     _n = _n * &2;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:187:10
+  --> $DIR/arithmetic_side_effects.rs:191:10
    |
 LL |     _n = 2 * _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:188:10
+  --> $DIR/arithmetic_side_effects.rs:192:10
    |
 LL |     _n = &2 * _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:189:10
+  --> $DIR/arithmetic_side_effects.rs:193:10
    |
 LL |     _n = 23 + &85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:190:10
+  --> $DIR/arithmetic_side_effects.rs:194:10
    |
 LL |     _n = &23 + 85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:191:10
+  --> $DIR/arithmetic_side_effects.rs:195:10
    |
 LL |     _n = &23 + &85;
    |          ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:194:13
+  --> $DIR/arithmetic_side_effects.rs:198:13
    |
 LL |     let _ = Custom + 0;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:195:13
+  --> $DIR/arithmetic_side_effects.rs:199:13
    |
 LL |     let _ = Custom + 1;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:196:13
+  --> $DIR/arithmetic_side_effects.rs:200:13
    |
 LL |     let _ = Custom + 2;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:197:13
+  --> $DIR/arithmetic_side_effects.rs:201:13
    |
 LL |     let _ = Custom + 0.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:198:13
+  --> $DIR/arithmetic_side_effects.rs:202:13
    |
 LL |     let _ = Custom + 1.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:199:13
+  --> $DIR/arithmetic_side_effects.rs:203:13
    |
 LL |     let _ = Custom + 2.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:200:13
+  --> $DIR/arithmetic_side_effects.rs:204:13
    |
 LL |     let _ = Custom - 0;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:201:13
+  --> $DIR/arithmetic_side_effects.rs:205:13
    |
 LL |     let _ = Custom - 1;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:202:13
+  --> $DIR/arithmetic_side_effects.rs:206:13
    |
 LL |     let _ = Custom - 2;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:203:13
+  --> $DIR/arithmetic_side_effects.rs:207:13
    |
 LL |     let _ = Custom - 0.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:204:13
+  --> $DIR/arithmetic_side_effects.rs:208:13
    |
 LL |     let _ = Custom - 1.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:205:13
+  --> $DIR/arithmetic_side_effects.rs:209:13
    |
 LL |     let _ = Custom - 2.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:206:13
+  --> $DIR/arithmetic_side_effects.rs:210:13
    |
 LL |     let _ = Custom / 0;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:207:13
+  --> $DIR/arithmetic_side_effects.rs:211:13
    |
 LL |     let _ = Custom / 1;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:208:13
+  --> $DIR/arithmetic_side_effects.rs:212:13
    |
 LL |     let _ = Custom / 2;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:209:13
+  --> $DIR/arithmetic_side_effects.rs:213:13
    |
 LL |     let _ = Custom / 0.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:210:13
+  --> $DIR/arithmetic_side_effects.rs:214:13
    |
 LL |     let _ = Custom / 1.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:211:13
+  --> $DIR/arithmetic_side_effects.rs:215:13
    |
 LL |     let _ = Custom / 2.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:212:13
+  --> $DIR/arithmetic_side_effects.rs:216:13
    |
 LL |     let _ = Custom * 0;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:213:13
+  --> $DIR/arithmetic_side_effects.rs:217:13
    |
 LL |     let _ = Custom * 1;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:214:13
+  --> $DIR/arithmetic_side_effects.rs:218:13
    |
 LL |     let _ = Custom * 2;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:215:13
+  --> $DIR/arithmetic_side_effects.rs:219:13
    |
 LL |     let _ = Custom * 0.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:216:13
+  --> $DIR/arithmetic_side_effects.rs:220:13
    |
 LL |     let _ = Custom * 1.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:217:13
+  --> $DIR/arithmetic_side_effects.rs:221:13
    |
 LL |     let _ = Custom * 2.0;
    |             ^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:220:10
+  --> $DIR/arithmetic_side_effects.rs:224:10
    |
 LL |     _n = -_n;
    |          ^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:221:10
+  --> $DIR/arithmetic_side_effects.rs:225:10
    |
 LL |     _n = -&_n;
    |          ^^^^
diff --git a/tests/ui/auxiliary/doc_unsafe_macros.rs b/tests/ui/auxiliary/doc_unsafe_macros.rs
index 869672d1eda..3d917e3dc75 100644
--- a/tests/ui/auxiliary/doc_unsafe_macros.rs
+++ b/tests/ui/auxiliary/doc_unsafe_macros.rs
@@ -6,3 +6,11 @@ macro_rules! undocd_unsafe {
         }
     };
 }
+#[macro_export]
+macro_rules! undocd_safe {
+    () => {
+        pub fn vey_oy() {
+            unimplemented!();
+        }
+    };
+}
diff --git a/tests/ui/blanket_clippy_restriction_lints.rs b/tests/ui/blanket_clippy_restriction_lints.rs
index d055f17526b..554745368bc 100644
--- a/tests/ui/blanket_clippy_restriction_lints.rs
+++ b/tests/ui/blanket_clippy_restriction_lints.rs
@@ -1,3 +1,5 @@
+// compile-flags: -W clippy::restriction
+
 #![warn(clippy::blanket_clippy_restriction_lints)]
 
 //! Test that the whole restriction group is not enabled
diff --git a/tests/ui/blanket_clippy_restriction_lints.stderr b/tests/ui/blanket_clippy_restriction_lints.stderr
index e83eb4d605a..2bf89ab69a4 100644
--- a/tests/ui/blanket_clippy_restriction_lints.stderr
+++ b/tests/ui/blanket_clippy_restriction_lints.stderr
@@ -1,27 +1,32 @@
-error: restriction lints are not meant to be all enabled
-  --> $DIR/blanket_clippy_restriction_lints.rs:4:9
+error: `clippy::restriction` is not meant to be enabled as a group
+   |
+   = note: because of the command line `--warn clippy::restriction`
+   = help: enable the restriction lints you need individually
+   = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
+
+error: `clippy::restriction` is not meant to be enabled as a group
+  --> $DIR/blanket_clippy_restriction_lints.rs:6:9
    |
 LL | #![warn(clippy::restriction)]
    |         ^^^^^^^^^^^^^^^^^^^
    |
-   = help: try enabling only the lints you really need
-   = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
+   = help: enable the restriction lints you need individually
 
-error: restriction lints are not meant to be all enabled
-  --> $DIR/blanket_clippy_restriction_lints.rs:5:9
+error: `clippy::restriction` is not meant to be enabled as a group
+  --> $DIR/blanket_clippy_restriction_lints.rs:7:9
    |
 LL | #![deny(clippy::restriction)]
    |         ^^^^^^^^^^^^^^^^^^^
    |
-   = help: try enabling only the lints you really need
+   = help: enable the restriction lints you need individually
 
-error: restriction lints are not meant to be all enabled
-  --> $DIR/blanket_clippy_restriction_lints.rs:6:11
+error: `clippy::restriction` is not meant to be enabled as a group
+  --> $DIR/blanket_clippy_restriction_lints.rs:8:11
    |
 LL | #![forbid(clippy::restriction)]
    |           ^^^^^^^^^^^^^^^^^^^
    |
-   = help: try enabling only the lints you really need
+   = help: enable the restriction lints you need individually
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/bool_to_int_with_if.fixed b/tests/ui/bool_to_int_with_if.fixed
index 2c8339cdd7f..37d3e3286a4 100644
--- a/tests/ui/bool_to_int_with_if.fixed
+++ b/tests/ui/bool_to_int_with_if.fixed
@@ -1,5 +1,6 @@
 // run-rustfix
 
+#![feature(let_chains)]
 #![warn(clippy::bool_to_int_with_if)]
 #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)]
 
@@ -76,6 +77,8 @@ fn main() {
         123
     };
 
+    pub const SHOULD_NOT_LINT: usize = if true { 1 } else { 0 };
+
     some_fn(a);
 }
 
@@ -89,3 +92,22 @@ fn side_effect() {}
 fn cond(a: bool, b: bool) -> bool {
     a || b
 }
+
+enum Enum {
+    A,
+    B,
+}
+
+fn if_let(a: Enum, b: Enum) {
+    if let Enum::A = a {
+        1
+    } else {
+        0
+    };
+
+    if let Enum::A = a && let Enum::B = b {
+        1
+    } else {
+        0
+    };
+}
diff --git a/tests/ui/bool_to_int_with_if.rs b/tests/ui/bool_to_int_with_if.rs
index 5d9496f0177..ebdf86fd185 100644
--- a/tests/ui/bool_to_int_with_if.rs
+++ b/tests/ui/bool_to_int_with_if.rs
@@ -1,5 +1,6 @@
 // run-rustfix
 
+#![feature(let_chains)]
 #![warn(clippy::bool_to_int_with_if)]
 #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)]
 
@@ -108,6 +109,8 @@ fn main() {
         123
     };
 
+    pub const SHOULD_NOT_LINT: usize = if true { 1 } else { 0 };
+
     some_fn(a);
 }
 
@@ -121,3 +124,22 @@ fn side_effect() {}
 fn cond(a: bool, b: bool) -> bool {
     a || b
 }
+
+enum Enum {
+    A,
+    B,
+}
+
+fn if_let(a: Enum, b: Enum) {
+    if let Enum::A = a {
+        1
+    } else {
+        0
+    };
+
+    if let Enum::A = a && let Enum::B = b {
+        1
+    } else {
+        0
+    };
+}
diff --git a/tests/ui/bool_to_int_with_if.stderr b/tests/ui/bool_to_int_with_if.stderr
index 4cb5531bef6..5cfb75cc0df 100644
--- a/tests/ui/bool_to_int_with_if.stderr
+++ b/tests/ui/bool_to_int_with_if.stderr
@@ -1,5 +1,5 @@
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:15:5
+  --> $DIR/bool_to_int_with_if.rs:16:5
    |
 LL | /     if a {
 LL | |         1
@@ -12,7 +12,7 @@ LL | |     };
    = note: `-D clippy::bool-to-int-with-if` implied by `-D warnings`
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:20:5
+  --> $DIR/bool_to_int_with_if.rs:21:5
    |
 LL | /     if a {
 LL | |         0
@@ -24,7 +24,7 @@ LL | |     };
    = note: `!a as i32` or `(!a).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:25:5
+  --> $DIR/bool_to_int_with_if.rs:26:5
    |
 LL | /     if !a {
 LL | |         1
@@ -36,7 +36,7 @@ LL | |     };
    = note: `!a as i32` or `(!a).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:30:5
+  --> $DIR/bool_to_int_with_if.rs:31:5
    |
 LL | /     if a || b {
 LL | |         1
@@ -48,7 +48,7 @@ LL | |     };
    = note: `(a || b) as i32` or `(a || b).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:35:5
+  --> $DIR/bool_to_int_with_if.rs:36:5
    |
 LL | /     if cond(a, b) {
 LL | |         1
@@ -60,7 +60,7 @@ LL | |     };
    = note: `cond(a, b) as i32` or `cond(a, b).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:40:5
+  --> $DIR/bool_to_int_with_if.rs:41:5
    |
 LL | /     if x + y < 4 {
 LL | |         1
@@ -72,7 +72,7 @@ LL | |     };
    = note: `(x + y < 4) as i32` or `(x + y < 4).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:49:12
+  --> $DIR/bool_to_int_with_if.rs:50:12
    |
 LL |       } else if b {
    |  ____________^
@@ -85,7 +85,7 @@ LL | |     };
    = note: `b as i32` or `b.into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:58:12
+  --> $DIR/bool_to_int_with_if.rs:59:12
    |
 LL |       } else if b {
    |  ____________^
@@ -98,7 +98,7 @@ LL | |     };
    = note: `!b as i32` or `(!b).into()` can also be valid options
 
 error: boolean to int conversion using if
-  --> $DIR/bool_to_int_with_if.rs:116:5
+  --> $DIR/bool_to_int_with_if.rs:119:5
    |
 LL |     if a { 1 } else { 0 }
    |     ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)`
diff --git a/tests/ui/cognitive_complexity.rs b/tests/ui/cognitive_complexity.rs
index 912e6788afd..07bdaff00dc 100644
--- a/tests/ui/cognitive_complexity.rs
+++ b/tests/ui/cognitive_complexity.rs
@@ -393,3 +393,19 @@ impl Moo {
         }
     }
 }
+
+#[clippy::cognitive_complexity = "1"]
+mod issue9300 {
+    async fn a() {
+        let a = 0;
+        if a == 0 {}
+    }
+
+    pub struct S;
+    impl S {
+        pub async fn async_method() {
+            let a = 0;
+            if a == 0 {}
+        }
+    }
+}
diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity.stderr
index d7f2f24e52f..5824631fa83 100644
--- a/tests/ui/cognitive_complexity.stderr
+++ b/tests/ui/cognitive_complexity.stderr
@@ -135,5 +135,21 @@ LL |     fn moo(&self) {
    |
    = help: you could split it up into multiple smaller functions
 
-error: aborting due to 17 previous errors
+error: the function has a cognitive complexity of (2/1)
+  --> $DIR/cognitive_complexity.rs:399:14
+   |
+LL |     async fn a() {
+   |              ^
+   |
+   = help: you could split it up into multiple smaller functions
+
+error: the function has a cognitive complexity of (2/1)
+  --> $DIR/cognitive_complexity.rs:406:22
+   |
+LL |         pub async fn async_method() {
+   |                      ^^^^^^^^^^^^
+   |
+   = help: you could split it up into multiple smaller functions
+
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/crashes/ice-2774.stderr b/tests/ui/crashes/ice-2774.stderr
index 0c2d48f938f..1f26c7f4db6 100644
--- a/tests/ui/crashes/ice-2774.stderr
+++ b/tests/ui/crashes/ice-2774.stderr
@@ -1,4 +1,4 @@
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/ice-2774.rs:15:1
    |
 LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
diff --git a/tests/ui/crashes/ice-9746.rs b/tests/ui/crashes/ice-9746.rs
new file mode 100644
index 00000000000..fbd373c70bf
--- /dev/null
+++ b/tests/ui/crashes/ice-9746.rs
@@ -0,0 +1,15 @@
+//! <https://github.com/rust-lang/rust-clippy/issues/9746#issuecomment-1297132880>
+
+trait Trait {}
+
+struct Struct<'a> {
+    _inner: &'a Struct<'a>,
+}
+
+impl Trait for Struct<'_> {}
+
+fn example<'a>(s: &'a Struct) -> Box<Box<dyn Trait + 'a>> {
+    Box::new(Box::new(Struct { _inner: s }))
+}
+
+fn main() {}
diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
index d68bbe78802..875d5ab4f21 100644
--- a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
+++ b/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
@@ -1,4 +1,4 @@
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/needless_lifetimes_impl_trait.rs:15:5
    |
 LL |     fn baz<'a>(&'a self) -> impl Foo + 'a {
diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs
index 4a5c597dda5..e1c9fe30a9d 100644
--- a/tests/ui/crate_level_checks/no_std_main_recursion.rs
+++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs
@@ -1,6 +1,5 @@
 // compile-flags: -Clink-arg=-nostartfiles
 // ignore-macos
-// ignore-windows
 
 #![feature(lang_items, start, libc)]
 #![no_std]
diff --git a/tests/ui/doc_errors.stderr b/tests/ui/doc_errors.stderr
index c7b616e2897..d74f2dbfe1b 100644
--- a/tests/ui/doc_errors.stderr
+++ b/tests/ui/doc_errors.stderr
@@ -1,52 +1,40 @@
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:7:1
    |
-LL | / pub fn pub_fn_missing_errors_header() -> Result<(), ()> {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub fn pub_fn_missing_errors_header() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::missing-errors-doc` implied by `-D warnings`
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:11:1
    |
-LL | / pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:16:1
    |
-LL | / pub fn pub_fn_returning_io_result() -> io::Result<()> {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub fn pub_fn_returning_io_result() -> io::Result<()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:21:1
    |
-LL | / pub async fn async_pub_fn_returning_io_result() -> io::Result<()> {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub async fn async_pub_fn_returning_io_result() -> io::Result<()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:51:5
    |
-LL | /     pub fn pub_method_missing_errors_header() -> Result<(), ()> {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
+LL |     pub fn pub_method_missing_errors_header() -> Result<(), ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:56:5
    |
-LL | /     pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
+LL |     pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function returning `Result` missing `# Errors` section
   --> $DIR/doc_errors.rs:85:5
diff --git a/tests/ui/doc_unnecessary_unsafe.rs b/tests/ui/doc_unnecessary_unsafe.rs
new file mode 100644
index 00000000000..d9e9363b0f4
--- /dev/null
+++ b/tests/ui/doc_unnecessary_unsafe.rs
@@ -0,0 +1,148 @@
+// aux-build:doc_unsafe_macros.rs
+
+#![allow(clippy::let_unit_value)]
+
+#[macro_use]
+extern crate doc_unsafe_macros;
+
+/// This is has no safety section, and does not need one either
+pub fn destroy_the_planet() {
+    unimplemented!();
+}
+
+/// This one does not need a `Safety` section
+///
+/// # Safety
+///
+/// This function shouldn't be called unless the horsemen are ready
+pub fn apocalypse(universe: &mut ()) {
+    unimplemented!();
+}
+
+/// This is a private function, skip to match behavior with `missing_safety_doc`.
+///
+/// # Safety
+///
+/// Boo!
+fn you_dont_see_me() {
+    unimplemented!();
+}
+
+mod private_mod {
+    /// This is public but unexported function, skip to match behavior with `missing_safety_doc`.
+    ///
+    /// # Safety
+    ///
+    /// Very safe!
+    pub fn only_crate_wide_accessible() {
+        unimplemented!();
+    }
+
+    /// # Safety
+    ///
+    /// Unnecessary safety!
+    pub fn republished() {
+        unimplemented!();
+    }
+}
+
+pub use private_mod::republished;
+
+pub trait SafeTraitSafeMethods {
+    fn woefully_underdocumented(self);
+
+    /// # Safety
+    ///
+    /// Unnecessary!
+    fn documented(self);
+}
+
+pub trait SafeTrait {
+    fn method();
+}
+
+/// # Safety
+///
+/// Unnecessary!
+pub trait DocumentedSafeTrait {
+    fn method2();
+}
+
+pub struct Struct;
+
+impl SafeTraitSafeMethods for Struct {
+    fn woefully_underdocumented(self) {
+        // all is well
+    }
+
+    fn documented(self) {
+        // all is still well
+    }
+}
+
+impl SafeTrait for Struct {
+    fn method() {}
+}
+
+impl DocumentedSafeTrait for Struct {
+    fn method2() {}
+}
+
+impl Struct {
+    /// # Safety
+    ///
+    /// Unnecessary!
+    pub fn documented() -> Self {
+        unimplemented!();
+    }
+
+    pub fn undocumented(&self) {
+        unimplemented!();
+    }
+
+    /// Private, fine again to stay consistent with `missing_safety_doc`.
+    ///
+    /// # Safety
+    ///
+    /// Unnecessary!
+    fn private(&self) {
+        unimplemented!();
+    }
+}
+
+macro_rules! very_safe {
+    () => {
+        pub fn whee() {
+            unimplemented!()
+        }
+
+        /// # Safety
+        ///
+        /// Driving is very safe already!
+        pub fn drive() {
+            whee()
+        }
+    };
+}
+
+very_safe!();
+
+// we don't lint code from external macros
+undocd_safe!();
+
+fn main() {}
+
+// do not lint if any parent has `#[doc(hidden)]` attribute
+// see #7347
+#[doc(hidden)]
+pub mod __macro {
+    pub struct T;
+    impl T {
+        pub unsafe fn f() {}
+    }
+}
+
+/// # Implementation safety
+pub trait DocumentedSafeTraitWithImplementationHeader {
+    fn method();
+}
diff --git a/tests/ui/doc_unnecessary_unsafe.stderr b/tests/ui/doc_unnecessary_unsafe.stderr
new file mode 100644
index 00000000000..83b2efbb346
--- /dev/null
+++ b/tests/ui/doc_unnecessary_unsafe.stderr
@@ -0,0 +1,51 @@
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:18:1
+   |
+LL | pub fn apocalypse(universe: &mut ()) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::unnecessary-safety-doc` implied by `-D warnings`
+
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:44:5
+   |
+LL |     pub fn republished() {
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:57:5
+   |
+LL |     fn documented(self);
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: docs for safe trait have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:67:1
+   |
+LL | pub trait DocumentedSafeTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:95:5
+   |
+LL |     pub fn documented() -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: safe function's docs have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:122:9
+   |
+LL |         pub fn drive() {
+   |         ^^^^^^^^^^^^^^
+...
+LL | very_safe!();
+   | ------------ in this macro invocation
+   |
+   = note: this error originates in the macro `very_safe` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: docs for safe trait have unnecessary `# Safety` section
+  --> $DIR/doc_unnecessary_unsafe.rs:146:1
+   |
+LL | pub trait DocumentedSafeTraitWithImplementationHeader {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/doc_unsafe.stderr b/tests/ui/doc_unsafe.stderr
index 904b88eaef6..a86e191370e 100644
--- a/tests/ui/doc_unsafe.stderr
+++ b/tests/ui/doc_unsafe.stderr
@@ -1,20 +1,16 @@
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:9:1
    |
-LL | / pub unsafe fn destroy_the_planet() {
-LL | |     unimplemented!();
-LL | | }
-   | |_^
+LL | pub unsafe fn destroy_the_planet() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::missing-safety-doc` implied by `-D warnings`
 
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:32:5
    |
-LL | /     pub unsafe fn republished() {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
+LL |     pub unsafe fn republished() {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:40:5
@@ -25,29 +21,23 @@ LL |     unsafe fn woefully_underdocumented(self);
 error: docs for unsafe trait missing `# Safety` section
   --> $DIR/doc_unsafe.rs:46:1
    |
-LL | / pub unsafe trait UnsafeTrait {
-LL | |     fn method();
-LL | | }
-   | |_^
+LL | pub unsafe trait UnsafeTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:76:5
    |
-LL | /     pub unsafe fn more_undocumented_unsafe() -> Self {
-LL | |         unimplemented!();
-LL | |     }
-   | |_____^
+LL |     pub unsafe fn more_undocumented_unsafe() -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsafe function's docs miss `# Safety` section
   --> $DIR/doc_unsafe.rs:92:9
    |
-LL | /         pub unsafe fn whee() {
-LL | |             unimplemented!()
-LL | |         }
-   | |_________^
+LL |         pub unsafe fn whee() {
+   |         ^^^^^^^^^^^^^^^^^^^^
 ...
-LL |   very_unsafe!();
-   |   -------------- in this macro invocation
+LL | very_unsafe!();
+   | -------------- in this macro invocation
    |
    = note: this error originates in the macro `very_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs
index 422f9486503..e7379550265 100644
--- a/tests/ui/eq_op.rs
+++ b/tests/ui/eq_op.rs
@@ -2,6 +2,7 @@
 
 #![warn(clippy::eq_op)]
 #![allow(clippy::double_parens, clippy::identity_op, clippy::nonminimal_bool)]
+#![allow(clippy::suspicious_xor_used_as_pow)]
 
 fn main() {
     // simple values and comparisons
diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr
index 313ceed2b41..d365ab27edc 100644
--- a/tests/ui/eq_op.stderr
+++ b/tests/ui/eq_op.stderr
@@ -1,5 +1,5 @@
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:8:13
+  --> $DIR/eq_op.rs:9:13
    |
 LL |     let _ = 1 == 1;
    |             ^^^^^^
@@ -7,163 +7,163 @@ LL |     let _ = 1 == 1;
    = note: `-D clippy::eq-op` implied by `-D warnings`
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:9:13
+  --> $DIR/eq_op.rs:10:13
    |
 LL |     let _ = "no" == "no";
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> $DIR/eq_op.rs:11:13
+  --> $DIR/eq_op.rs:12:13
    |
 LL |     let _ = false != false;
    |             ^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `<`
-  --> $DIR/eq_op.rs:12:13
+  --> $DIR/eq_op.rs:13:13
    |
 LL |     let _ = 1.5 < 1.5;
    |             ^^^^^^^^^
 
 error: equal expressions as operands to `>=`
-  --> $DIR/eq_op.rs:13:13
+  --> $DIR/eq_op.rs:14:13
    |
 LL |     let _ = 1u64 >= 1u64;
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `&`
-  --> $DIR/eq_op.rs:16:13
+  --> $DIR/eq_op.rs:17:13
    |
 LL |     let _ = (1u32 as u64) & (1u32 as u64);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `^`
-  --> $DIR/eq_op.rs:19:17
+  --> $DIR/eq_op.rs:20:17
    |
 LL |         let _ = 1 ^ ((((((1))))));
    |                 ^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `<`
-  --> $DIR/eq_op.rs:23:13
+  --> $DIR/eq_op.rs:24:13
    |
 LL |     let _ = (-(2) < -(2));
    |             ^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:24:13
+  --> $DIR/eq_op.rs:25:13
    |
 LL |     let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&`
-  --> $DIR/eq_op.rs:24:14
+  --> $DIR/eq_op.rs:25:14
    |
 LL |     let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1));
    |              ^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&`
-  --> $DIR/eq_op.rs:24:35
+  --> $DIR/eq_op.rs:25:35
    |
 LL |     let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1));
    |                                   ^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:25:13
+  --> $DIR/eq_op.rs:26:13
    |
 LL |     let _ = (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> $DIR/eq_op.rs:28:13
+  --> $DIR/eq_op.rs:29:13
    |
 LL |     let _ = ([1] != [1]);
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> $DIR/eq_op.rs:29:13
+  --> $DIR/eq_op.rs:30:13
    |
 LL |     let _ = ((1, 2) != (1, 2));
    |             ^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:33:13
+  --> $DIR/eq_op.rs:34:13
    |
 LL |     let _ = 1 + 1 == 2;
    |             ^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:34:13
+  --> $DIR/eq_op.rs:35:13
    |
 LL |     let _ = 1 - 1 == 0;
    |             ^^^^^^^^^^
 
 error: equal expressions as operands to `-`
-  --> $DIR/eq_op.rs:34:13
+  --> $DIR/eq_op.rs:35:13
    |
 LL |     let _ = 1 - 1 == 0;
    |             ^^^^^
 
 error: equal expressions as operands to `-`
-  --> $DIR/eq_op.rs:36:13
+  --> $DIR/eq_op.rs:37:13
    |
 LL |     let _ = 1 - 1;
    |             ^^^^^
 
 error: equal expressions as operands to `/`
-  --> $DIR/eq_op.rs:37:13
+  --> $DIR/eq_op.rs:38:13
    |
 LL |     let _ = 1 / 1;
    |             ^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:38:13
+  --> $DIR/eq_op.rs:39:13
    |
 LL |     let _ = true && true;
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `||`
-  --> $DIR/eq_op.rs:40:13
+  --> $DIR/eq_op.rs:41:13
    |
 LL |     let _ = true || true;
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:45:13
+  --> $DIR/eq_op.rs:46:13
    |
 LL |     let _ = a == b && b == a;
    |             ^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:46:13
+  --> $DIR/eq_op.rs:47:13
    |
 LL |     let _ = a != b && b != a;
    |             ^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:47:13
+  --> $DIR/eq_op.rs:48:13
    |
 LL |     let _ = a < b && b > a;
    |             ^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `&&`
-  --> $DIR/eq_op.rs:48:13
+  --> $DIR/eq_op.rs:49:13
    |
 LL |     let _ = a <= b && b >= a;
    |             ^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:51:13
+  --> $DIR/eq_op.rs:52:13
    |
 LL |     let _ = a == a;
    |             ^^^^^^
 
 error: equal expressions as operands to `/`
-  --> $DIR/eq_op.rs:61:20
+  --> $DIR/eq_op.rs:62:20
    |
 LL |     const D: u32 = A / A;
    |                    ^^^^^
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:92:5
+  --> $DIR/eq_op.rs:93:5
    |
 LL |     (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed
index 687efdada6e..9af2ba96272 100644
--- a/tests/ui/equatable_if_let.fixed
+++ b/tests/ui/equatable_if_let.fixed
@@ -23,6 +23,11 @@ struct Struct {
     b: bool,
 }
 
+struct NoPartialEqStruct {
+    a: i32,
+    b: bool,
+}
+
 enum NotPartialEq {
     A,
     B,
@@ -47,6 +52,7 @@ fn main() {
     let e = Enum::UnitVariant;
     let f = NotPartialEq::A;
     let g = NotStructuralEq::A;
+    let h = NoPartialEqStruct { a: 2, b: false };
 
     // true
 
@@ -66,10 +72,11 @@ fn main() {
     if let Some(3 | 4) = c {}
     if let Struct { a, b: false } = d {}
     if let Struct { a: 2, b: x } = d {}
-    if let NotPartialEq::A = f {}
+    if matches!(f, NotPartialEq::A) {}
     if g == NotStructuralEq::A {}
-    if let Some(NotPartialEq::A) = Some(f) {}
+    if matches!(Some(f), Some(NotPartialEq::A)) {}
     if Some(g) == Some(NotStructuralEq::A) {}
+    if matches!(h, NoPartialEqStruct { a: 2, b: false }) {}
 
     macro_rules! m1 {
         (x) => {
diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs
index 8c467d14d2a..c3626c081dd 100644
--- a/tests/ui/equatable_if_let.rs
+++ b/tests/ui/equatable_if_let.rs
@@ -23,6 +23,11 @@ struct Struct {
     b: bool,
 }
 
+struct NoPartialEqStruct {
+    a: i32,
+    b: bool,
+}
+
 enum NotPartialEq {
     A,
     B,
@@ -47,6 +52,7 @@ fn main() {
     let e = Enum::UnitVariant;
     let f = NotPartialEq::A;
     let g = NotStructuralEq::A;
+    let h = NoPartialEqStruct { a: 2, b: false };
 
     // true
 
@@ -70,6 +76,7 @@ fn main() {
     if let NotStructuralEq::A = g {}
     if let Some(NotPartialEq::A) = Some(f) {}
     if let Some(NotStructuralEq::A) = Some(g) {}
+    if let NoPartialEqStruct { a: 2, b: false } = h {}
 
     macro_rules! m1 {
         (x) => {
diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr
index 9c4c3cc3682..40ca75b8da2 100644
--- a/tests/ui/equatable_if_let.stderr
+++ b/tests/ui/equatable_if_let.stderr
@@ -1,5 +1,5 @@
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:53:8
+  --> $DIR/equatable_if_let.rs:59:8
    |
 LL |     if let 2 = a {}
    |        ^^^^^^^^^ help: try: `a == 2`
@@ -7,64 +7,82 @@ LL |     if let 2 = a {}
    = note: `-D clippy::equatable-if-let` implied by `-D warnings`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:54:8
+  --> $DIR/equatable_if_let.rs:60:8
    |
 LL |     if let Ordering::Greater = a.cmp(&b) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:55:8
+  --> $DIR/equatable_if_let.rs:61:8
    |
 LL |     if let Some(2) = c {}
    |        ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:56:8
+  --> $DIR/equatable_if_let.rs:62:8
    |
 LL |     if let Struct { a: 2, b: false } = d {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:57:8
+  --> $DIR/equatable_if_let.rs:63:8
    |
 LL |     if let Enum::TupleVariant(32, 64) = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:58:8
+  --> $DIR/equatable_if_let.rs:64:8
    |
 LL |     if let Enum::RecordVariant { a: 64, b: 32 } = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:59:8
+  --> $DIR/equatable_if_let.rs:65:8
    |
 LL |     if let Enum::UnitVariant = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:60:8
+  --> $DIR/equatable_if_let.rs:66:8
    |
 LL |     if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
 
+error: this pattern matching can be expressed using `matches!`
+  --> $DIR/equatable_if_let.rs:75:8
+   |
+LL |     if let NotPartialEq::A = f {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)`
+
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:70:8
+  --> $DIR/equatable_if_let.rs:76:8
    |
 LL |     if let NotStructuralEq::A = g {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
 
+error: this pattern matching can be expressed using `matches!`
+  --> $DIR/equatable_if_let.rs:77:8
+   |
+LL |     if let Some(NotPartialEq::A) = Some(f) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))`
+
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:72:8
+  --> $DIR/equatable_if_let.rs:78:8
    |
 LL |     if let Some(NotStructuralEq::A) = Some(g) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
 
-error: this pattern matching can be expressed using equality
+error: this pattern matching can be expressed using `matches!`
   --> $DIR/equatable_if_let.rs:79:8
    |
+LL |     if let NoPartialEqStruct { a: 2, b: false } = h {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:86:8
+   |
 LL |     if let m1!(x) = "abc" {
    |        ^^^^^^^^^^^^^^^^^^ help: try: `"abc" == m1!(x)`
 
-error: aborting due to 11 previous errors
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui/expect.stderr b/tests/ui/expect.stderr
index f6738865cac..c08e0dbbf74 100644
--- a/tests/ui/expect.stderr
+++ b/tests/ui/expect.stderr
@@ -1,4 +1,4 @@
-error: used `expect()` on `an Option` value
+error: used `expect()` on an `Option` value
   --> $DIR/expect.rs:5:13
    |
 LL |     let _ = opt.expect("");
@@ -7,7 +7,7 @@ LL |     let _ = opt.expect("");
    = help: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
-error: used `expect()` on `a Result` value
+error: used `expect()` on a `Result` value
   --> $DIR/expect.rs:10:13
    |
 LL |     let _ = res.expect("");
@@ -15,7 +15,7 @@ LL |     let _ = res.expect("");
    |
    = help: if this value is an `Err`, it will panic
 
-error: used `expect_err()` on `a Result` value
+error: used `expect_err()` on a `Result` value
   --> $DIR/expect.rs:11:13
    |
 LL |     let _ = res.expect_err("");
diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed
index d1d35e5c0eb..59ff5e4040a 100644
--- a/tests/ui/explicit_auto_deref.fixed
+++ b/tests/ui/explicit_auto_deref.fixed
@@ -266,4 +266,15 @@ fn main() {
         }
         x
     };
+
+    trait WithAssoc {
+        type Assoc: ?Sized;
+    }
+    impl WithAssoc for String {
+        type Assoc = str;
+    }
+    fn takes_assoc<T: WithAssoc>(_: &T::Assoc) -> T {
+        unimplemented!()
+    }
+    let _: String = takes_assoc(&*String::new());
 }
diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs
index deedafad153..bcfb60c3278 100644
--- a/tests/ui/explicit_auto_deref.rs
+++ b/tests/ui/explicit_auto_deref.rs
@@ -266,4 +266,15 @@ fn main() {
         }
         *x
     };
+
+    trait WithAssoc {
+        type Assoc: ?Sized;
+    }
+    impl WithAssoc for String {
+        type Assoc = str;
+    }
+    fn takes_assoc<T: WithAssoc>(_: &T::Assoc) -> T {
+        unimplemented!()
+    }
+    let _: String = takes_assoc(&*String::new());
 }
diff --git a/tests/ui/fn_params_excessive_bools.rs b/tests/ui/fn_params_excessive_bools.rs
index f805bcc9ba8..f53e531629a 100644
--- a/tests/ui/fn_params_excessive_bools.rs
+++ b/tests/ui/fn_params_excessive_bools.rs
@@ -2,6 +2,7 @@
 #![allow(clippy::too_many_arguments)]
 
 extern "C" {
+    // Should not lint, most of the time users have no control over extern function signatures
     fn f(_: bool, _: bool, _: bool, _: bool);
 }
 
@@ -22,8 +23,12 @@ fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {}
 
 struct S;
 trait Trait {
+    // should warn for trait functions with and without body
     fn f(_: bool, _: bool, _: bool, _: bool);
     fn g(_: bool, _: bool, _: bool, _: Vec<u32>);
+    #[allow(clippy::fn_params_excessive_bools)]
+    fn h(_: bool, _: bool, _: bool, _: bool, _: bool, _: bool);
+    fn i(_: bool, _: bool, _: bool, _: bool) {}
 }
 
 impl S {
@@ -34,8 +39,11 @@ impl S {
 }
 
 impl Trait for S {
+    // Should not lint because the trait might not be changeable by the user
+    // We only lint in the trait definition
     fn f(_: bool, _: bool, _: bool, _: bool) {}
     fn g(_: bool, _: bool, _: bool, _: Vec<u32>) {}
+    fn h(_: bool, _: bool, _: bool, _: bool, _: bool, _: bool) {}
 }
 
 fn main() {
diff --git a/tests/ui/fn_params_excessive_bools.stderr b/tests/ui/fn_params_excessive_bools.stderr
index 11627105691..43363b46972 100644
--- a/tests/ui/fn_params_excessive_bools.stderr
+++ b/tests/ui/fn_params_excessive_bools.stderr
@@ -1,5 +1,5 @@
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:18:1
+  --> $DIR/fn_params_excessive_bools.rs:19:1
    |
 LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    = note: `-D clippy::fn-params-excessive-bools` implied by `-D warnings`
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:21:1
+  --> $DIR/fn_params_excessive_bools.rs:22:1
    |
 LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:25:5
+  --> $DIR/fn_params_excessive_bools.rs:27:5
    |
 LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,15 @@ LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:30:5
+  --> $DIR/fn_params_excessive_bools.rs:31:5
+   |
+LL |     fn i(_: bool, _: bool, _: bool, _: bool) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider refactoring bools into two-variant enums
+
+error: more than 3 bools in function parameters
+  --> $DIR/fn_params_excessive_bools.rs:35:5
    |
 LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +40,7 @@ LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:42:5
+  --> $DIR/fn_params_excessive_bools.rs:50:5
    |
 LL | /     fn n(_: bool, _: u32, _: bool, _: Box<u32>, _: bool, _: bool) {
 LL | |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
@@ -42,12 +50,12 @@ LL | |     }
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:43:9
+  --> $DIR/fn_params_excessive_bools.rs:51:9
    |
 LL |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider refactoring bools into two-variant enums
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/tests/ui/from_raw_with_void_ptr.rs b/tests/ui/from_raw_with_void_ptr.rs
new file mode 100644
index 00000000000..8484da2415a
--- /dev/null
+++ b/tests/ui/from_raw_with_void_ptr.rs
@@ -0,0 +1,34 @@
+#![warn(clippy::from_raw_with_void_ptr)]
+
+use std::ffi::c_void;
+use std::rc::Rc;
+use std::sync::Arc;
+
+fn main() {
+    // must lint
+    let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
+    let _ = unsafe { Box::from_raw(ptr) };
+
+    // shouldn't be linted
+    let _ = unsafe { Box::from_raw(ptr as *mut usize) };
+
+    // shouldn't be linted
+    let should_not_lint_ptr = Box::into_raw(Box::new(12u8)) as *mut u8;
+    let _ = unsafe { Box::from_raw(should_not_lint_ptr as *mut u8) };
+
+    // must lint
+    let ptr = Rc::into_raw(Rc::new(42usize)) as *mut c_void;
+    let _ = unsafe { Rc::from_raw(ptr) };
+
+    // must lint
+    let ptr = Arc::into_raw(Arc::new(42usize)) as *mut c_void;
+    let _ = unsafe { Arc::from_raw(ptr) };
+
+    // must lint
+    let ptr = std::rc::Weak::into_raw(Rc::downgrade(&Rc::new(42usize))) as *mut c_void;
+    let _ = unsafe { std::rc::Weak::from_raw(ptr) };
+
+    // must lint
+    let ptr = std::sync::Weak::into_raw(Arc::downgrade(&Arc::new(42usize))) as *mut c_void;
+    let _ = unsafe { std::sync::Weak::from_raw(ptr) };
+}
diff --git a/tests/ui/from_raw_with_void_ptr.stderr b/tests/ui/from_raw_with_void_ptr.stderr
new file mode 100644
index 00000000000..96e4af12ba3
--- /dev/null
+++ b/tests/ui/from_raw_with_void_ptr.stderr
@@ -0,0 +1,63 @@
+error: creating a `Box` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:10:22
+   |
+LL |     let _ = unsafe { Box::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:10:36
+   |
+LL |     let _ = unsafe { Box::from_raw(ptr) };
+   |                                    ^^^
+   = note: `-D clippy::from-raw-with-void-ptr` implied by `-D warnings`
+
+error: creating a `Rc` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:21:22
+   |
+LL |     let _ = unsafe { Rc::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:21:35
+   |
+LL |     let _ = unsafe { Rc::from_raw(ptr) };
+   |                                   ^^^
+
+error: creating a `Arc` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:25:22
+   |
+LL |     let _ = unsafe { Arc::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:25:36
+   |
+LL |     let _ = unsafe { Arc::from_raw(ptr) };
+   |                                    ^^^
+
+error: creating a `Weak` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:29:22
+   |
+LL |     let _ = unsafe { std::rc::Weak::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:29:46
+   |
+LL |     let _ = unsafe { std::rc::Weak::from_raw(ptr) };
+   |                                              ^^^
+
+error: creating a `Weak` from a void raw pointer
+  --> $DIR/from_raw_with_void_ptr.rs:33:22
+   |
+LL |     let _ = unsafe { std::sync::Weak::from_raw(ptr) };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: cast this to a pointer of the appropriate type
+  --> $DIR/from_raw_with_void_ptr.rs:33:48
+   |
+LL |     let _ = unsafe { std::sync::Weak::from_raw(ptr) };
+   |                                                ^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr
index 937f8590408..6dee4d5b4b6 100644
--- a/tests/ui/get_unwrap.stderr
+++ b/tests/ui/get_unwrap.stderr
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(clippy::get_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:35:17
    |
 LL |         let _ = boxed_slice.get(1).unwrap();
@@ -25,7 +25,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:36:17
    |
 LL |         let _ = some_slice.get(0).unwrap();
@@ -39,7 +39,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:37:17
    |
 LL |         let _ = some_vec.get(0).unwrap();
@@ -53,7 +53,7 @@ error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:38:17
    |
 LL |         let _ = some_vecdeque.get(0).unwrap();
@@ -67,7 +67,7 @@ error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:39:17
    |
 LL |         let _ = some_hashmap.get(&1).unwrap();
@@ -81,7 +81,7 @@ error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:40:17
    |
 LL |         let _ = some_btreemap.get(&1).unwrap();
@@ -95,7 +95,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:44:22
    |
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
@@ -109,7 +109,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:49:10
    |
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
@@ -123,7 +123,7 @@ error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and mor
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:50:10
    |
 LL |         *some_slice.get_mut(0).unwrap() = 1;
@@ -137,7 +137,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:51:10
    |
 LL |         *some_vec.get_mut(0).unwrap() = 1;
@@ -151,7 +151,7 @@ error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:52:10
    |
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
@@ -165,7 +165,7 @@ error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more conc
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:64:17
    |
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
@@ -179,7 +179,7 @@ error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/get_unwrap.rs:65:17
    |
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
diff --git a/tests/ui/infallible_destructuring_match.fixed b/tests/ui/infallible_destructuring_match.fixed
index b8e40d99553..61985e56b76 100644
--- a/tests/ui/infallible_destructuring_match.fixed
+++ b/tests/ui/infallible_destructuring_match.fixed
@@ -9,6 +9,9 @@ enum SingleVariantEnum {
 
 struct TupleStruct(i32);
 
+struct NonCopy;
+struct TupleStructWithNonCopy(NonCopy);
+
 enum EmptyEnum {}
 
 macro_rules! match_enum {
@@ -71,6 +74,15 @@ fn infallible_destructuring_match_struct() {
     let TupleStruct(data) = wrapper;
 }
 
+fn infallible_destructuring_match_struct_with_noncopy() {
+    let wrapper = TupleStructWithNonCopy(NonCopy);
+
+    // This should lint! (keeping `ref` in the suggestion)
+    let TupleStructWithNonCopy(ref data) = wrapper;
+
+    let TupleStructWithNonCopy(ref data) = wrapper;
+}
+
 macro_rules! match_never_enum {
     ($param:expr) => {
         let data = match $param {
diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs
index 106cd438b90..f2768245bbc 100644
--- a/tests/ui/infallible_destructuring_match.rs
+++ b/tests/ui/infallible_destructuring_match.rs
@@ -9,6 +9,9 @@ enum SingleVariantEnum {
 
 struct TupleStruct(i32);
 
+struct NonCopy;
+struct TupleStructWithNonCopy(NonCopy);
+
 enum EmptyEnum {}
 
 macro_rules! match_enum {
@@ -75,6 +78,17 @@ fn infallible_destructuring_match_struct() {
     let TupleStruct(data) = wrapper;
 }
 
+fn infallible_destructuring_match_struct_with_noncopy() {
+    let wrapper = TupleStructWithNonCopy(NonCopy);
+
+    // This should lint! (keeping `ref` in the suggestion)
+    let data = match wrapper {
+        TupleStructWithNonCopy(ref n) => n,
+    };
+
+    let TupleStructWithNonCopy(ref data) = wrapper;
+}
+
 macro_rules! match_never_enum {
     ($param:expr) => {
         let data = match $param {
diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr
index 1b78db42014..f8a50f0223d 100644
--- a/tests/ui/infallible_destructuring_match.stderr
+++ b/tests/ui/infallible_destructuring_match.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let`
-  --> $DIR/infallible_destructuring_match.rs:26:5
+  --> $DIR/infallible_destructuring_match.rs:29:5
    |
 LL | /     let data = match wrapper {
 LL | |         SingleVariantEnum::Variant(i) => i,
@@ -9,7 +9,7 @@ LL | |     };
    = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings`
 
 error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let`
-  --> $DIR/infallible_destructuring_match.rs:58:5
+  --> $DIR/infallible_destructuring_match.rs:61:5
    |
 LL | /     let data = match wrapper {
 LL | |         TupleStruct(i) => i,
@@ -17,12 +17,20 @@ LL | |     };
    | |______^ help: try this: `let TupleStruct(data) = wrapper;`
 
 error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let`
-  --> $DIR/infallible_destructuring_match.rs:90:5
+  --> $DIR/infallible_destructuring_match.rs:85:5
+   |
+LL | /     let data = match wrapper {
+LL | |         TupleStructWithNonCopy(ref n) => n,
+LL | |     };
+   | |______^ help: try this: `let TupleStructWithNonCopy(ref data) = wrapper;`
+
+error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let`
+  --> $DIR/infallible_destructuring_match.rs:104:5
    |
 LL | /     let data = match wrapper {
 LL | |         Ok(i) => i,
 LL | |     };
    | |______^ help: try this: `let Ok(data) = wrapper;`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr
index fb2a93c9580..fd553aa4538 100644
--- a/tests/ui/issue_4266.stderr
+++ b/tests/ui/issue_4266.stderr
@@ -1,4 +1,4 @@
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/issue_4266.rs:4:1
    |
 LL | async fn sink1<'a>(_: &'a str) {} // lint
@@ -6,7 +6,7 @@ LL | async fn sink1<'a>(_: &'a str) {} // lint
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/issue_4266.rs:8:1
    |
 LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
diff --git a/tests/ui/let_underscore_drop.rs b/tests/ui/let_underscore_drop.rs
deleted file mode 100644
index 11b50492ab2..00000000000
--- a/tests/ui/let_underscore_drop.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![warn(clippy::let_underscore_drop)]
-#![allow(clippy::let_unit_value)]
-
-struct Droppable;
-
-impl Drop for Droppable {
-    fn drop(&mut self) {}
-}
-
-fn main() {
-    let unit = ();
-    let boxed = Box::new(());
-    let droppable = Droppable;
-    let optional = Some(Droppable);
-
-    let _ = ();
-    let _ = Box::new(());
-    let _ = Droppable;
-    let _ = Some(Droppable);
-
-    // no lint for reference
-    let _ = droppable_ref();
-}
-
-#[must_use]
-fn droppable_ref() -> &'static mut Droppable {
-    unimplemented!()
-}
diff --git a/tests/ui/let_underscore_drop.stderr b/tests/ui/let_underscore_drop.stderr
deleted file mode 100644
index 324b7cd431d..00000000000
--- a/tests/ui/let_underscore_drop.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-error: non-binding `let` on a type that implements `Drop`
-  --> $DIR/let_underscore_drop.rs:17:5
-   |
-LL |     let _ = Box::new(());
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-   = note: `-D clippy::let-underscore-drop` implied by `-D warnings`
-
-error: non-binding `let` on a type that implements `Drop`
-  --> $DIR/let_underscore_drop.rs:18:5
-   |
-LL |     let _ = Droppable;
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding `let` on a type that implements `Drop`
-  --> $DIR/let_underscore_drop.rs:19:5
-   |
-LL |     let _ = Some(Droppable);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: aborting due to 3 previous errors
-
diff --git a/tests/ui/let_underscore_future.rs b/tests/ui/let_underscore_future.rs
new file mode 100644
index 00000000000..d8f54cdca91
--- /dev/null
+++ b/tests/ui/let_underscore_future.rs
@@ -0,0 +1,20 @@
+use std::future::Future;
+
+async fn some_async_fn() {}
+
+fn sync_side_effects() {}
+fn custom() -> impl Future<Output = ()> {
+    sync_side_effects();
+    async {}
+}
+
+fn do_something_to_future(future: &mut impl Future<Output = ()>) {}
+
+fn main() {
+    let _ = some_async_fn();
+    let _ = custom();
+
+    let mut future = some_async_fn();
+    do_something_to_future(&mut future);
+    let _ = future;
+}
diff --git a/tests/ui/let_underscore_future.stderr b/tests/ui/let_underscore_future.stderr
new file mode 100644
index 00000000000..33a748736a8
--- /dev/null
+++ b/tests/ui/let_underscore_future.stderr
@@ -0,0 +1,27 @@
+error: non-binding `let` on a future
+  --> $DIR/let_underscore_future.rs:14:5
+   |
+LL |     let _ = some_async_fn();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider awaiting the future or dropping explicitly with `std::mem::drop`
+   = note: `-D clippy::let-underscore-future` implied by `-D warnings`
+
+error: non-binding `let` on a future
+  --> $DIR/let_underscore_future.rs:15:5
+   |
+LL |     let _ = custom();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider awaiting the future or dropping explicitly with `std::mem::drop`
+
+error: non-binding `let` on a future
+  --> $DIR/let_underscore_future.rs:19:5
+   |
+LL |     let _ = future;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: consider awaiting the future or dropping explicitly with `std::mem::drop`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/let_underscore_lock.rs b/tests/ui/let_underscore_lock.rs
index 7a7c4e92499..4dff4d766bc 100644
--- a/tests/ui/let_underscore_lock.rs
+++ b/tests/ui/let_underscore_lock.rs
@@ -3,20 +3,6 @@
 extern crate parking_lot;
 
 fn main() {
-    let m = std::sync::Mutex::new(());
-    let rw = std::sync::RwLock::new(());
-
-    let _ = m.lock();
-    let _ = rw.read();
-    let _ = rw.write();
-    let _ = m.try_lock();
-    let _ = rw.try_read();
-    let _ = rw.try_write();
-
-    // These shouldn't throw an error.
-    let _ = m;
-    let _ = rw;
-
     use parking_lot::{lock_api::RawMutex, Mutex, RwLock};
 
     let p_m: Mutex<()> = Mutex::const_new(RawMutex::INIT, ());
@@ -34,3 +20,20 @@ fn main() {
     let _ = p_m1;
     let _ = p_rw;
 }
+
+fn uplifted() {
+    // shouldn't lint std locks as they were uplifted as rustc's `let_underscore_lock`
+
+    let m = std::sync::Mutex::new(());
+    let rw = std::sync::RwLock::new(());
+
+    let _ = m.lock();
+    let _ = rw.read();
+    let _ = rw.write();
+    let _ = m.try_lock();
+    let _ = rw.try_read();
+    let _ = rw.try_write();
+
+    let _ = m;
+    let _ = rw;
+}
diff --git a/tests/ui/let_underscore_lock.stderr b/tests/ui/let_underscore_lock.stderr
index d7779e7b6c4..f137d411209 100644
--- a/tests/ui/let_underscore_lock.stderr
+++ b/tests/ui/let_underscore_lock.stderr
@@ -1,83 +1,35 @@
-error: non-binding let on a synchronization lock
+error: non-binding `let` on a synchronization lock
   --> $DIR/let_underscore_lock.rs:9:5
    |
-LL |     let _ = m.lock();
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-   = note: `-D clippy::let-underscore-lock` implied by `-D warnings`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:10:5
-   |
-LL |     let _ = rw.read();
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:11:5
-   |
-LL |     let _ = rw.write();
-   |     ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:12:5
-   |
-LL |     let _ = m.try_lock();
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:13:5
-   |
-LL |     let _ = rw.try_read();
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:14:5
-   |
-LL |     let _ = rw.try_write();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
-
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:23:5
-   |
 LL |     let _ = p_m.lock();
    |     ^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
+   = note: `-D clippy::let-underscore-lock` implied by `-D warnings`
 
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:26:5
+error: non-binding `let` on a synchronization lock
+  --> $DIR/let_underscore_lock.rs:12:5
    |
 LL |     let _ = p_m1.lock();
    |     ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
 
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:29:5
+error: non-binding `let` on a synchronization lock
+  --> $DIR/let_underscore_lock.rs:15:5
    |
 LL |     let _ = p_rw.read();
    |     ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
 
-error: non-binding let on a synchronization lock
-  --> $DIR/let_underscore_lock.rs:30:5
+error: non-binding `let` on a synchronization lock
+  --> $DIR/let_underscore_lock.rs:16:5
    |
 LL |     let _ = p_rw.write();
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
 
-error: aborting due to 10 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/let_underscore_must_use.stderr b/tests/ui/let_underscore_must_use.stderr
index bae60f2ff9b..28d760eb46e 100644
--- a/tests/ui/let_underscore_must_use.stderr
+++ b/tests/ui/let_underscore_must_use.stderr
@@ -1,4 +1,4 @@
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:67:5
    |
 LL |     let _ = f();
@@ -7,7 +7,7 @@ LL |     let _ = f();
    = help: consider explicitly using function result
    = note: `-D clippy::let-underscore-must-use` implied by `-D warnings`
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:68:5
    |
 LL |     let _ = g();
@@ -15,7 +15,7 @@ LL |     let _ = g();
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:70:5
    |
 LL |     let _ = l(0_u32);
@@ -23,7 +23,7 @@ LL |     let _ = l(0_u32);
    |
    = help: consider explicitly using function result
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:74:5
    |
 LL |     let _ = s.f();
@@ -31,7 +31,7 @@ LL |     let _ = s.f();
    |
    = help: consider explicitly using function result
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:75:5
    |
 LL |     let _ = s.g();
@@ -39,7 +39,7 @@ LL |     let _ = s.g();
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:78:5
    |
 LL |     let _ = S::h();
@@ -47,7 +47,7 @@ LL |     let _ = S::h();
    |
    = help: consider explicitly using function result
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:79:5
    |
 LL |     let _ = S::p();
@@ -55,7 +55,7 @@ LL |     let _ = S::p();
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:81:5
    |
 LL |     let _ = S::a();
@@ -63,7 +63,7 @@ LL |     let _ = S::a();
    |
    = help: consider explicitly using function result
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:83:5
    |
 LL |     let _ = if true { Ok(()) } else { Err(()) };
@@ -71,7 +71,7 @@ LL |     let _ = if true { Ok(()) } else { Err(()) };
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on a result of a `#[must_use]` function
+error: non-binding `let` on a result of a `#[must_use]` function
   --> $DIR/let_underscore_must_use.rs:87:5
    |
 LL |     let _ = a.is_ok();
@@ -79,7 +79,7 @@ LL |     let _ = a.is_ok();
    |
    = help: consider explicitly using function result
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:89:5
    |
 LL |     let _ = a.map(|_| ());
@@ -87,7 +87,7 @@ LL |     let _ = a.map(|_| ());
    |
    = help: consider explicitly using expression value
 
-error: non-binding let on an expression with `#[must_use]` type
+error: non-binding `let` on an expression with `#[must_use]` type
   --> $DIR/let_underscore_must_use.rs:91:5
    |
 LL |     let _ = a;
diff --git a/tests/ui/manual_flatten.rs b/tests/ui/manual_flatten.rs
index 96cd87c0e19..552213a7ff2 100644
--- a/tests/ui/manual_flatten.rs
+++ b/tests/ui/manual_flatten.rs
@@ -10,7 +10,7 @@ fn main() {
         }
     }
 
-    // Test for loop over implicitly implicitly adjusted `Iterator` with `if let` statement
+    // Test for loop over implicitly adjusted `Iterator` with `if let` statement
     let y: Vec<Result<i32, i32>> = vec![];
     for n in y.clone() {
         if let Ok(n) = n {
diff --git a/tests/ui/manual_instant_elapsed.fixed b/tests/ui/manual_instant_elapsed.fixed
index 0fa776b7b2e..85a91543c89 100644
--- a/tests/ui/manual_instant_elapsed.fixed
+++ b/tests/ui/manual_instant_elapsed.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 #![warn(clippy::manual_instant_elapsed)]
 #![allow(clippy::unnecessary_operation)]
+#![allow(clippy::unchecked_duration_subtraction)]
 #![allow(unused_variables)]
 #![allow(unused_must_use)]
 
diff --git a/tests/ui/manual_instant_elapsed.rs b/tests/ui/manual_instant_elapsed.rs
index 5b11b84535d..c98cb15b916 100644
--- a/tests/ui/manual_instant_elapsed.rs
+++ b/tests/ui/manual_instant_elapsed.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 #![warn(clippy::manual_instant_elapsed)]
 #![allow(clippy::unnecessary_operation)]
+#![allow(clippy::unchecked_duration_subtraction)]
 #![allow(unused_variables)]
 #![allow(unused_must_use)]
 
diff --git a/tests/ui/manual_instant_elapsed.stderr b/tests/ui/manual_instant_elapsed.stderr
index 5537f5642a2..4ce1f689107 100644
--- a/tests/ui/manual_instant_elapsed.stderr
+++ b/tests/ui/manual_instant_elapsed.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of `Instant::elapsed`
-  --> $DIR/manual_instant_elapsed.rs:17:20
+  --> $DIR/manual_instant_elapsed.rs:18:20
    |
 LL |     let duration = Instant::now() - prev_instant;
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `prev_instant.elapsed()`
@@ -7,7 +7,7 @@ LL |     let duration = Instant::now() - prev_instant;
    = note: `-D clippy::manual-instant-elapsed` implied by `-D warnings`
 
 error: manual implementation of `Instant::elapsed`
-  --> $DIR/manual_instant_elapsed.rs:26:5
+  --> $DIR/manual_instant_elapsed.rs:27:5
    |
 LL |     Instant::now() - *ref_to_instant; // to ensure parens are added correctly
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*ref_to_instant).elapsed()`
diff --git a/tests/ui/manual_is_ascii_check.fixed b/tests/ui/manual_is_ascii_check.fixed
new file mode 100644
index 00000000000..765bb785994
--- /dev/null
+++ b/tests/ui/manual_is_ascii_check.fixed
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![allow(unused, dead_code)]
+#![warn(clippy::manual_is_ascii_check)]
+
+fn main() {
+    assert!('x'.is_ascii_lowercase());
+    assert!('X'.is_ascii_uppercase());
+    assert!(b'x'.is_ascii_lowercase());
+    assert!(b'X'.is_ascii_uppercase());
+
+    let num = '2';
+    assert!(num.is_ascii_digit());
+    assert!(b'1'.is_ascii_digit());
+    assert!('x'.is_ascii_alphabetic());
+
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+}
+
+fn msrv_1_23() {
+    #![clippy::msrv = "1.23"]
+
+    assert!(matches!(b'1', b'0'..=b'9'));
+    assert!(matches!('X', 'A'..='Z'));
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+}
+
+fn msrv_1_24() {
+    #![clippy::msrv = "1.24"]
+
+    assert!(b'1'.is_ascii_digit());
+    assert!('X'.is_ascii_uppercase());
+    assert!('x'.is_ascii_alphabetic());
+}
+
+fn msrv_1_46() {
+    #![clippy::msrv = "1.46"]
+    const FOO: bool = matches!('x', '0'..='9');
+}
+
+fn msrv_1_47() {
+    #![clippy::msrv = "1.47"]
+    const FOO: bool = 'x'.is_ascii_digit();
+}
diff --git a/tests/ui/manual_is_ascii_check.rs b/tests/ui/manual_is_ascii_check.rs
new file mode 100644
index 00000000000..be133161041
--- /dev/null
+++ b/tests/ui/manual_is_ascii_check.rs
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![allow(unused, dead_code)]
+#![warn(clippy::manual_is_ascii_check)]
+
+fn main() {
+    assert!(matches!('x', 'a'..='z'));
+    assert!(matches!('X', 'A'..='Z'));
+    assert!(matches!(b'x', b'a'..=b'z'));
+    assert!(matches!(b'X', b'A'..=b'Z'));
+
+    let num = '2';
+    assert!(matches!(num, '0'..='9'));
+    assert!(matches!(b'1', b'0'..=b'9'));
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+}
+
+fn msrv_1_23() {
+    #![clippy::msrv = "1.23"]
+
+    assert!(matches!(b'1', b'0'..=b'9'));
+    assert!(matches!('X', 'A'..='Z'));
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+}
+
+fn msrv_1_24() {
+    #![clippy::msrv = "1.24"]
+
+    assert!(matches!(b'1', b'0'..=b'9'));
+    assert!(matches!('X', 'A'..='Z'));
+    assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+}
+
+fn msrv_1_46() {
+    #![clippy::msrv = "1.46"]
+    const FOO: bool = matches!('x', '0'..='9');
+}
+
+fn msrv_1_47() {
+    #![clippy::msrv = "1.47"]
+    const FOO: bool = matches!('x', '0'..='9');
+}
diff --git a/tests/ui/manual_is_ascii_check.stderr b/tests/ui/manual_is_ascii_check.stderr
new file mode 100644
index 00000000000..c0a9d4db1a1
--- /dev/null
+++ b/tests/ui/manual_is_ascii_check.stderr
@@ -0,0 +1,70 @@
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:8:13
+   |
+LL |     assert!(matches!('x', 'a'..='z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_lowercase()`
+   |
+   = note: `-D clippy::manual-is-ascii-check` implied by `-D warnings`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:9:13
+   |
+LL |     assert!(matches!('X', 'A'..='Z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:10:13
+   |
+LL |     assert!(matches!(b'x', b'a'..=b'z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'x'.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:11:13
+   |
+LL |     assert!(matches!(b'X', b'A'..=b'Z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'X'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:14:13
+   |
+LL |     assert!(matches!(num, '0'..='9'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:15:13
+   |
+LL |     assert!(matches!(b'1', b'0'..=b'9'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:16:13
+   |
+LL |     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:32:13
+   |
+LL |     assert!(matches!(b'1', b'0'..=b'9'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:33:13
+   |
+LL |     assert!(matches!('X', 'A'..='Z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:34:13
+   |
+LL |     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:44:23
+   |
+LL |     const FOO: bool = matches!('x', '0'..='9');
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()`
+
+error: aborting due to 11 previous errors
+
diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs
new file mode 100644
index 00000000000..2ef40e5911a
--- /dev/null
+++ b/tests/ui/manual_let_else.rs
@@ -0,0 +1,237 @@
+#![allow(unused_braces, unused_variables, dead_code)]
+#![allow(
+    clippy::collapsible_else_if,
+    clippy::unused_unit,
+    clippy::let_unit_value,
+    clippy::match_single_binding,
+    clippy::never_loop
+)]
+#![warn(clippy::manual_let_else)]
+
+fn g() -> Option<()> {
+    None
+}
+
+fn main() {}
+
+fn fire() {
+    let v = if let Some(v_some) = g() { v_some } else { return };
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        return;
+    };
+
+    let v = if let Some(v) = g() {
+        // Blocks around the identity should have no impact
+        {
+            { v }
+        }
+    } else {
+        // Some computation should still make it fire
+        g();
+        return;
+    };
+
+    // continue and break diverge
+    loop {
+        let v = if let Some(v_some) = g() { v_some } else { continue };
+        let v = if let Some(v_some) = g() { v_some } else { break };
+    }
+
+    // panic also diverges
+    let v = if let Some(v_some) = g() { v_some } else { panic!() };
+
+    // abort also diverges
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        std::process::abort()
+    };
+
+    // If whose two branches diverge also diverges
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        if true { return } else { panic!() }
+    };
+
+    // Diverging after an if still makes the block diverge:
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        if true {}
+        panic!();
+    };
+
+    // A match diverges if all branches diverge:
+    // Note: the corresponding let-else requires a ; at the end of the match
+    // as otherwise the type checker does not turn it into a ! type.
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        match () {
+            _ if panic!() => {},
+            _ => panic!(),
+        }
+    };
+
+    // An if's expression can cause divergence:
+    let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
+
+    // An expression of a match can cause divergence:
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        match panic!() {
+            _ => {},
+        }
+    };
+
+    // Top level else if
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else if true {
+        return;
+    } else {
+        panic!("diverge");
+    };
+
+    // All match arms diverge
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        match (g(), g()) {
+            (Some(_), None) => return,
+            (None, Some(_)) => {
+                if true {
+                    return;
+                } else {
+                    panic!();
+                }
+            },
+            _ => return,
+        }
+    };
+
+    // Tuples supported for the declared variables
+    let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
+        v_some
+    } else {
+        return;
+    };
+
+    // Tuples supported for the identity block and pattern
+    let v = if let (Some(v_some), w_some) = (g(), 0) {
+        (w_some, v_some)
+    } else {
+        return;
+    };
+
+    // entirely inside macro lints
+    macro_rules! create_binding_if_some {
+        ($n:ident, $e:expr) => {
+            let $n = if let Some(v) = $e { v } else { return };
+        };
+    }
+    create_binding_if_some!(w, g());
+}
+
+fn not_fire() {
+    let v = if let Some(v_some) = g() {
+        // Nothing returned. Should not fire.
+    } else {
+        return;
+    };
+
+    let w = 0;
+    let v = if let Some(v_some) = g() {
+        // Different variable than v_some. Should not fire.
+        w
+    } else {
+        return;
+    };
+
+    let v = if let Some(v_some) = g() {
+        // Computation in then clause. Should not fire.
+        g();
+        v_some
+    } else {
+        return;
+    };
+
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        if false {
+            return;
+        }
+        // This doesn't diverge. Should not fire.
+        ()
+    };
+
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        // There is one match arm that doesn't diverge. Should not fire.
+        match (g(), g()) {
+            (Some(_), None) => return,
+            (None, Some(_)) => return,
+            (Some(_), Some(_)) => (),
+            _ => return,
+        }
+    };
+
+    let v = if let Some(v_some) = g() {
+        v_some
+    } else {
+        // loop with a break statement inside does not diverge.
+        loop {
+            break;
+        }
+    };
+
+    enum Uninhabited {}
+    fn un() -> Uninhabited {
+        panic!()
+    }
+    let v = if let Some(v_some) = None {
+        v_some
+    } else {
+        // Don't lint if the type is uninhabited but not !
+        un()
+    };
+
+    fn question_mark() -> Option<()> {
+        let v = if let Some(v) = g() {
+            v
+        } else {
+            // Question mark does not diverge
+            g()?
+        };
+        Some(v)
+    }
+
+    // Macro boundary inside let
+    macro_rules! some_or_return {
+        ($e:expr) => {
+            if let Some(v) = $e { v } else { return }
+        };
+    }
+    let v = some_or_return!(g());
+
+    // Also macro boundary inside let, but inside a macro
+    macro_rules! create_binding_if_some_nf {
+        ($n:ident, $e:expr) => {
+            let $n = some_or_return!($e);
+        };
+    }
+    create_binding_if_some_nf!(v, g());
+
+    // Already a let-else
+    let Some(a) = (if let Some(b) = Some(Some(())) { b } else { return }) else { panic!() };
+
+    // If a type annotation is present, don't lint as
+    // expressing the type might be too hard
+    let v: () = if let Some(v_some) = g() { v_some } else { panic!() };
+}
diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr
new file mode 100644
index 00000000000..453b68b8bd0
--- /dev/null
+++ b/tests/ui/manual_let_else.stderr
@@ -0,0 +1,263 @@
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:18:5
+   |
+LL |     let v = if let Some(v_some) = g() { v_some } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { return };`
+   |
+   = note: `-D clippy::manual-let-else` implied by `-D warnings`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:19:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:25:5
+   |
+LL | /     let v = if let Some(v) = g() {
+LL | |         // Blocks around the identity should have no impact
+LL | |         {
+LL | |             { v }
+...  |
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v) = g() else {
+LL +         // Some computation should still make it fire
+LL +         g();
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:38:9
+   |
+LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { continue };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:39:9
+   |
+LL |         let v = if let Some(v_some) = g() { v_some } else { break };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { break };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:43:5
+   |
+LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { panic!() };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:46:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         std::process::abort()
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         std::process::abort()
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:53:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         if true { return } else { panic!() }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         if true { return } else { panic!() }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:60:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         if true {}
+LL | |         panic!();
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         if true {}
+LL +         panic!();
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:70:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         match () {
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         match () {
+LL +             _ if panic!() => {},
+LL +             _ => panic!(),
+LL +         }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:80:5
+   |
+LL |     let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { if panic!() {} };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:83:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         match panic!() {
+LL | |             _ => {},
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         match panic!() {
+LL +             _ => {},
+LL +         }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:92:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else if true {
+LL | |         return;
+LL | |     } else {
+LL | |         panic!("diverge");
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else { if true {
+LL +         return;
+LL +     } else {
+LL +         panic!("diverge");
+LL +     } };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:101:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |         v_some
+LL | |     } else {
+LL | |         match (g(), g()) {
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g() else {
+LL +         match (g(), g()) {
+LL +             (Some(_), None) => return,
+LL +             (None, Some(_)) => {
+LL +                 if true {
+LL +                     return;
+LL +                 } else {
+LL +                     panic!();
+LL +                 }
+LL +             },
+LL +             _ => return,
+LL +         }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:118:5
+   |
+LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
+LL | |         v_some
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v_some) = g().map(|v| (v, 42)) else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:125:5
+   |
+LL | /     let v = if let (Some(v_some), w_some) = (g(), 0) {
+LL | |         (w_some, v_some)
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let (Some(v_some), w_some) = (g(), 0) else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:134:13
+   |
+LL |             let $n = if let Some(v) = $e { v } else { return };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
+...
+LL |     create_binding_if_some!(w, g());
+   |     ------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 17 previous errors
+
diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs
new file mode 100644
index 00000000000..93c86ca24fe
--- /dev/null
+++ b/tests/ui/manual_let_else_match.rs
@@ -0,0 +1,121 @@
+#![allow(unused_braces, unused_variables, dead_code)]
+#![allow(clippy::collapsible_else_if, clippy::let_unit_value)]
+#![warn(clippy::manual_let_else)]
+// Ensure that we don't conflict with match -> if let lints
+#![warn(clippy::single_match_else, clippy::single_match)]
+
+fn f() -> Result<u32, u32> {
+    Ok(0)
+}
+
+fn g() -> Option<()> {
+    None
+}
+
+fn h() -> (Option<()>, Option<()>) {
+    (None, None)
+}
+
+enum Variant {
+    Foo,
+    Bar(u32),
+    Baz(u32),
+}
+
+fn build_enum() -> Variant {
+    Variant::Foo
+}
+
+fn main() {}
+
+fn fire() {
+    let v = match g() {
+        Some(v_some) => v_some,
+        None => return,
+    };
+
+    let v = match g() {
+        Some(v_some) => v_some,
+        _ => return,
+    };
+
+    loop {
+        // More complex pattern for the identity arm and diverging arm
+        let v = match h() {
+            (Some(_), Some(_)) | (None, None) => continue,
+            (Some(v), None) | (None, Some(v)) => v,
+        };
+        // Custom enums are supported as long as the "else" arm is a simple _
+        let v = match build_enum() {
+            _ => continue,
+            Variant::Bar(v) | Variant::Baz(v) => v,
+        };
+    }
+
+    // There is a _ in the diverging arm
+    // TODO also support unused bindings aka _v
+    let v = match f() {
+        Ok(v) => v,
+        Err(_) => return,
+    };
+
+    // Err(()) is an allowed pattern
+    let v = match f().map_err(|_| ()) {
+        Ok(v) => v,
+        Err(()) => return,
+    };
+}
+
+fn not_fire() {
+    // Multiple diverging arms
+    let v = match h() {
+        _ => panic!(),
+        (None, Some(_v)) => return,
+        (Some(v), None) => v,
+    };
+
+    // Multiple identity arms
+    let v = match h() {
+        _ => panic!(),
+        (None, Some(v)) => v,
+        (Some(v), None) => v,
+    };
+
+    // No diverging arm at all, only identity arms.
+    // This is no case for let else, but destructuring assignment.
+    let v = match f() {
+        Ok(v) => v,
+        Err(e) => e,
+    };
+
+    // The identity arm has a guard
+    let v = match g() {
+        Some(v) if g().is_none() => v,
+        _ => return,
+    };
+
+    // The diverging arm has a guard
+    let v = match f() {
+        Err(v) if v > 0 => panic!(),
+        Ok(v) | Err(v) => v,
+    };
+
+    // The diverging arm creates a binding
+    let v = match f() {
+        Ok(v) => v,
+        Err(e) => panic!("error: {e}"),
+    };
+
+    // Custom enum where the diverging arm
+    // explicitly mentions the variant
+    let v = match build_enum() {
+        Variant::Foo => return,
+        Variant::Bar(v) | Variant::Baz(v) => v,
+    };
+
+    // The custom enum is surrounded by an Err()
+    let v = match Err(build_enum()) {
+        Ok(v) | Err(Variant::Bar(v) | Variant::Baz(v)) => v,
+        Err(Variant::Foo) => return,
+    };
+}
diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr
new file mode 100644
index 00000000000..38be5ac5454
--- /dev/null
+++ b/tests/ui/manual_let_else_match.stderr
@@ -0,0 +1,58 @@
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:32:5
+   |
+LL | /     let v = match g() {
+LL | |         Some(v_some) => v_some,
+LL | |         None => return,
+LL | |     };
+   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+   |
+   = note: `-D clippy::manual-let-else` implied by `-D warnings`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:37:5
+   |
+LL | /     let v = match g() {
+LL | |         Some(v_some) => v_some,
+LL | |         _ => return,
+LL | |     };
+   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:44:9
+   |
+LL | /         let v = match h() {
+LL | |             (Some(_), Some(_)) | (None, None) => continue,
+LL | |             (Some(v), None) | (None, Some(v)) => v,
+LL | |         };
+   | |__________^ help: consider writing: `let (Some(v), None) | (None, Some(v)) = h() else { continue };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:49:9
+   |
+LL | /         let v = match build_enum() {
+LL | |             _ => continue,
+LL | |             Variant::Bar(v) | Variant::Baz(v) => v,
+LL | |         };
+   | |__________^ help: consider writing: `let Variant::Bar(v) | Variant::Baz(v) = build_enum() else { continue };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:57:5
+   |
+LL | /     let v = match f() {
+LL | |         Ok(v) => v,
+LL | |         Err(_) => return,
+LL | |     };
+   | |______^ help: consider writing: `let Ok(v) = f() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:63:5
+   |
+LL | /     let v = match f().map_err(|_| ()) {
+LL | |         Ok(v) => v,
+LL | |         Err(()) => return,
+LL | |     };
+   | |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/manual_ok_or.fixed b/tests/ui/manual_ok_or.fixed
index d864f855453..fc8511626b3 100644
--- a/tests/ui/manual_ok_or.fixed
+++ b/tests/ui/manual_ok_or.fixed
@@ -1,5 +1,6 @@
 // run-rustfix
 #![warn(clippy::manual_ok_or)]
+#![allow(clippy::or_fun_call)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::redundant_closure)]
 #![allow(dead_code)]
diff --git a/tests/ui/manual_ok_or.rs b/tests/ui/manual_ok_or.rs
index 6264768460e..b5303d33f5f 100644
--- a/tests/ui/manual_ok_or.rs
+++ b/tests/ui/manual_ok_or.rs
@@ -1,5 +1,6 @@
 // run-rustfix
 #![warn(clippy::manual_ok_or)]
+#![allow(clippy::or_fun_call)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::redundant_closure)]
 #![allow(dead_code)]
diff --git a/tests/ui/manual_ok_or.stderr b/tests/ui/manual_ok_or.stderr
index 65459a09738..b4a17f143e3 100644
--- a/tests/ui/manual_ok_or.stderr
+++ b/tests/ui/manual_ok_or.stderr
@@ -1,5 +1,5 @@
 error: this pattern reimplements `Option::ok_or`
-  --> $DIR/manual_ok_or.rs:11:5
+  --> $DIR/manual_ok_or.rs:12:5
    |
 LL |     foo.map_or(Err("error"), |v| Ok(v));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `foo.ok_or("error")`
@@ -7,19 +7,19 @@ LL |     foo.map_or(Err("error"), |v| Ok(v));
    = note: `-D clippy::manual-ok-or` implied by `-D warnings`
 
 error: this pattern reimplements `Option::ok_or`
-  --> $DIR/manual_ok_or.rs:14:5
+  --> $DIR/manual_ok_or.rs:15:5
    |
 LL |     foo.map_or(Err("error"), Ok);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `foo.ok_or("error")`
 
 error: this pattern reimplements `Option::ok_or`
-  --> $DIR/manual_ok_or.rs:17:5
+  --> $DIR/manual_ok_or.rs:18:5
    |
 LL |     None::<i32>.map_or(Err("error"), |v| Ok(v));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `None::<i32>.ok_or("error")`
 
 error: this pattern reimplements `Option::ok_or`
-  --> $DIR/manual_ok_or.rs:21:5
+  --> $DIR/manual_ok_or.rs:22:5
    |
 LL | /     foo.map_or(Err::<i32, &str>(
 LL | |         &format!(
diff --git a/tests/ui/map_flatten_fixable.fixed b/tests/ui/map_flatten_fixable.fixed
index 312819a0a2c..53628ef6531 100644
--- a/tests/ui/map_flatten_fixable.fixed
+++ b/tests/ui/map_flatten_fixable.fixed
@@ -1,7 +1,6 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
-#![allow(clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::redundant_closure)]
diff --git a/tests/ui/map_flatten_fixable.rs b/tests/ui/map_flatten_fixable.rs
index 3fbf4f9a1b0..76016c8ed3c 100644
--- a/tests/ui/map_flatten_fixable.rs
+++ b/tests/ui/map_flatten_fixable.rs
@@ -1,7 +1,6 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
-#![allow(clippy::let_underscore_drop)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::redundant_closure)]
diff --git a/tests/ui/map_flatten_fixable.stderr b/tests/ui/map_flatten_fixable.stderr
index c91f0b9ae94..b6b0c4d09c3 100644
--- a/tests/ui/map_flatten_fixable.stderr
+++ b/tests/ui/map_flatten_fixable.stderr
@@ -1,5 +1,5 @@
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:18:47
+  --> $DIR/map_flatten_fixable.rs:17:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
@@ -7,43 +7,43 @@ LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
    = note: `-D clippy::map-flatten` implied by `-D warnings`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:19:47
+  --> $DIR/map_flatten_fixable.rs:18:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:20:47
+  --> $DIR/map_flatten_fixable.rs:19:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:21:47
+  --> $DIR/map_flatten_fixable.rs:20:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:24:47
+  --> $DIR/map_flatten_fixable.rs:23:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on `Option`
-  --> $DIR/map_flatten_fixable.rs:27:40
+  --> $DIR/map_flatten_fixable.rs:26:40
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
    |                                        ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Result`
-  --> $DIR/map_flatten_fixable.rs:30:42
+  --> $DIR/map_flatten_fixable.rs:29:42
    |
 LL |     let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
    |                                          ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:39:10
+  --> $DIR/map_flatten_fixable.rs:38:10
    |
 LL |           .map(|n| match n {
    |  __________^
@@ -72,7 +72,7 @@ LL ~         });
    |
 
 error: called `map(..).flatten()` on `Option`
-  --> $DIR/map_flatten_fixable.rs:59:10
+  --> $DIR/map_flatten_fixable.rs:58:10
    |
 LL |           .map(|_| {
    |  __________^
diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed
index 2498007694c..968f462f8a0 100644
--- a/tests/ui/match_expr_like_matches_macro.fixed
+++ b/tests/ui/match_expr_like_matches_macro.fixed
@@ -2,7 +2,12 @@
 
 #![feature(custom_inner_attributes)]
 #![warn(clippy::match_like_matches_macro)]
-#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
+#![allow(
+    unreachable_patterns,
+    dead_code,
+    clippy::equatable_if_let,
+    clippy::needless_borrowed_reference
+)]
 
 fn main() {
     let x = Some(5);
diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs
index b4e48499bd0..c6b479e27c5 100644
--- a/tests/ui/match_expr_like_matches_macro.rs
+++ b/tests/ui/match_expr_like_matches_macro.rs
@@ -2,7 +2,12 @@
 
 #![feature(custom_inner_attributes)]
 #![warn(clippy::match_like_matches_macro)]
-#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
+#![allow(
+    unreachable_patterns,
+    dead_code,
+    clippy::equatable_if_let,
+    clippy::needless_borrowed_reference
+)]
 
 fn main() {
     let x = Some(5);
diff --git a/tests/ui/match_expr_like_matches_macro.stderr b/tests/ui/match_expr_like_matches_macro.stderr
index f1d1c23aeb0..a4df8008ac2 100644
--- a/tests/ui/match_expr_like_matches_macro.stderr
+++ b/tests/ui/match_expr_like_matches_macro.stderr
@@ -1,5 +1,5 @@
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:11:14
+  --> $DIR/match_expr_like_matches_macro.rs:16:14
    |
 LL |       let _y = match x {
    |  ______________^
@@ -11,7 +11,7 @@ LL | |     };
    = note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:17:14
+  --> $DIR/match_expr_like_matches_macro.rs:22:14
    |
 LL |       let _w = match x {
    |  ______________^
@@ -21,7 +21,7 @@ LL | |     };
    | |_____^ help: try this: `matches!(x, Some(_))`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/match_expr_like_matches_macro.rs:23:14
+  --> $DIR/match_expr_like_matches_macro.rs:28:14
    |
 LL |       let _z = match x {
    |  ______________^
@@ -33,7 +33,7 @@ LL | |     };
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:29:15
+  --> $DIR/match_expr_like_matches_macro.rs:34:15
    |
 LL |       let _zz = match x {
    |  _______________^
@@ -43,13 +43,13 @@ LL | |     };
    | |_____^ help: try this: `!matches!(x, Some(r) if r == 0)`
 
 error: if let .. else expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:35:16
+  --> $DIR/match_expr_like_matches_macro.rs:40:16
    |
 LL |     let _zzz = if let Some(5) = x { true } else { false };
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:59:20
+  --> $DIR/match_expr_like_matches_macro.rs:64:20
    |
 LL |           let _ans = match x {
    |  ____________________^
@@ -60,7 +60,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:69:20
+  --> $DIR/match_expr_like_matches_macro.rs:74:20
    |
 LL |           let _ans = match x {
    |  ____________________^
@@ -73,7 +73,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:79:20
+  --> $DIR/match_expr_like_matches_macro.rs:84:20
    |
 LL |           let _ans = match x {
    |  ____________________^
@@ -84,7 +84,7 @@ LL | |         };
    | |_________^ help: try this: `!matches!(x, E::B(_) | E::C)`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:139:18
+  --> $DIR/match_expr_like_matches_macro.rs:144:18
    |
 LL |           let _z = match &z {
    |  __________________^
@@ -94,7 +94,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(z, Some(3))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:148:18
+  --> $DIR/match_expr_like_matches_macro.rs:153:18
    |
 LL |           let _z = match &z {
    |  __________________^
@@ -104,7 +104,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(&z, Some(3))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:165:21
+  --> $DIR/match_expr_like_matches_macro.rs:170:21
    |
 LL |               let _ = match &z {
    |  _____________________^
@@ -114,7 +114,7 @@ LL | |             };
    | |_____________^ help: try this: `matches!(&z, AnEnum::X)`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:179:20
+  --> $DIR/match_expr_like_matches_macro.rs:184:20
    |
 LL |           let _res = match &val {
    |  ____________________^
@@ -124,7 +124,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(&val, &Some(ref _a))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:191:20
+  --> $DIR/match_expr_like_matches_macro.rs:196:20
    |
 LL |           let _res = match &val {
    |  ____________________^
@@ -134,7 +134,7 @@ LL | |         };
    | |_________^ help: try this: `matches!(&val, &Some(ref _a))`
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_expr_like_matches_macro.rs:251:14
+  --> $DIR/match_expr_like_matches_macro.rs:256:14
    |
 LL |       let _y = match Some(5) {
    |  ______________^
diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr
index c9ded7f1ad0..183c262ce0b 100644
--- a/tests/ui/missing_panics_doc.stderr
+++ b/tests/ui/missing_panics_doc.stderr
@@ -1,11 +1,8 @@
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:6:1
    |
-LL | / pub fn unwrap() {
-LL | |     let result = Err("Hi");
-LL | |     result.unwrap()
-LL | | }
-   | |_^
+LL | pub fn unwrap() {
+   | ^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:8:5
@@ -17,10 +14,8 @@ LL |     result.unwrap()
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:12:1
    |
-LL | / pub fn panic() {
-LL | |     panic!("This function panics")
-LL | | }
-   | |_^
+LL | pub fn panic() {
+   | ^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:13:5
@@ -31,10 +26,8 @@ LL |     panic!("This function panics")
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:17:1
    |
-LL | / pub fn todo() {
-LL | |     todo!()
-LL | | }
-   | |_^
+LL | pub fn todo() {
+   | ^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:18:5
@@ -45,14 +38,8 @@ LL |     todo!()
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:22:1
    |
-LL | / pub fn inner_body(opt: Option<u32>) {
-LL | |     opt.map(|x| {
-LL | |         if x == 10 {
-LL | |             panic!()
-LL | |         }
-LL | |     });
-LL | | }
-   | |_^
+LL | pub fn inner_body(opt: Option<u32>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:25:13
@@ -63,10 +50,8 @@ LL |             panic!()
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:31:1
    |
-LL | / pub fn unreachable_and_panic() {
-LL | |     if true { unreachable!() } else { panic!() }
-LL | | }
-   | |_^
+LL | pub fn unreachable_and_panic() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:32:39
@@ -77,11 +62,8 @@ LL |     if true { unreachable!() } else { panic!() }
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:36:1
    |
-LL | / pub fn assert_eq() {
-LL | |     let x = 0;
-LL | |     assert_eq!(x, 0);
-LL | | }
-   | |_^
+LL | pub fn assert_eq() {
+   | ^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:38:5
@@ -92,11 +74,8 @@ LL |     assert_eq!(x, 0);
 error: docs for function which may panic missing `# Panics` section
   --> $DIR/missing_panics_doc.rs:42:1
    |
-LL | / pub fn assert_ne() {
-LL | |     let x = 0;
-LL | |     assert_ne!(x, 0);
-LL | | }
-   | |_^
+LL | pub fn assert_ne() {
+   | ^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
   --> $DIR/missing_panics_doc.rs:44:5
diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs
index 370dbd58821..7de15330594 100644
--- a/tests/ui/mut_from_ref.rs
+++ b/tests/ui/mut_from_ref.rs
@@ -1,4 +1,4 @@
-#![allow(unused)]
+#![allow(unused, clippy::needless_lifetimes)]
 #![warn(clippy::mut_from_ref)]
 
 struct Foo;
diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs
index ac8fd9d8fb0..ee3a856566c 100644
--- a/tests/ui/mut_mut.rs
+++ b/tests/ui/mut_mut.rs
@@ -57,3 +57,20 @@ fn issue6922() {
     // do not lint from an external macro
     mut_mut!();
 }
+
+mod issue9035 {
+    use std::fmt::Display;
+
+    struct Foo<'a> {
+        inner: &'a mut dyn Display,
+    }
+
+    impl Foo<'_> {
+        fn foo(&mut self) {
+            let hlp = &mut self.inner;
+            bar(hlp);
+        }
+    }
+
+    fn bar(_: &mut impl Display) {}
+}
diff --git a/tests/ui/mut_range_bound.rs b/tests/ui/mut_range_bound.rs
index e1ae1ef9282..7fdeb27ed98 100644
--- a/tests/ui/mut_range_bound.rs
+++ b/tests/ui/mut_range_bound.rs
@@ -76,7 +76,7 @@ fn mut_range_bound_no_immediate_break() {
     let mut n = 3;
     for i in n..10 {
         if n == 4 {
-            n = 1; // FIXME: warning because is is not immediately followed by break
+            n = 1; // FIXME: warning because it is not immediately followed by break
             let _ = 2;
             break;
         }
diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr
index e0c8dced382..b679b7a0aaf 100644
--- a/tests/ui/mut_range_bound.stderr
+++ b/tests/ui/mut_range_bound.stderr
@@ -50,7 +50,7 @@ LL |         m = 2; // warning because it is not immediately followed by break
 error: attempt to mutate range bound within loop
   --> $DIR/mut_range_bound.rs:79:13
    |
-LL |             n = 1; // FIXME: warning because is is not immediately followed by break
+LL |             n = 1; // FIXME: warning because it is not immediately followed by break
    |             ^
    |
    = note: the range of the loop is unchanged
diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed
index 340e89d2db1..85b6b639d55 100644
--- a/tests/ui/needless_borrow.fixed
+++ b/tests/ui/needless_borrow.fixed
@@ -385,3 +385,128 @@ mod used_more_than_once {
     fn use_x(_: impl AsRef<str>) {}
     fn use_x_again(_: impl AsRef<str>) {}
 }
+
+// https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280
+#[allow(dead_code)]
+mod issue_9111 {
+    struct A;
+
+    impl Extend<u8> for A {
+        fn extend<T: IntoIterator<Item = u8>>(&mut self, _: T) {
+            unimplemented!()
+        }
+    }
+
+    impl<'a> Extend<&'a u8> for A {
+        fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, _: T) {
+            unimplemented!()
+        }
+    }
+
+    fn main() {
+        let mut a = A;
+        a.extend(&[]); // vs a.extend([]);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9710 {
+    fn main() {
+        let string = String::new();
+        for _i in 0..10 {
+            f(&string);
+        }
+    }
+
+    fn f<T: AsRef<str>>(_: T) {}
+}
+
+#[allow(dead_code)]
+mod issue_9739 {
+    fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
+
+    fn main() {
+        foo(if std::env::var_os("HI").is_some() {
+            &[0]
+        } else {
+            &[] as &[u32]
+        });
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9739_method_variant {
+    struct S;
+
+    impl S {
+        fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
+    }
+
+    fn main() {
+        S.foo(if std::env::var_os("HI").is_some() {
+            &[0]
+        } else {
+            &[] as &[u32]
+        });
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782 {
+    fn foo<T: AsRef<[u8]>>(t: T) {
+        println!("{}", std::mem::size_of::<T>());
+        let _t: &[u8] = t.as_ref();
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        // 100
+        foo::<[u8; 100]>(a);
+        foo(a);
+
+        // 16
+        foo::<&[u8]>(&a);
+        foo(a.as_slice());
+
+        // 8
+        foo::<&[u8; 100]>(&a);
+        foo(a);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782_type_relative_variant {
+    struct S;
+
+    impl S {
+        fn foo<T: AsRef<[u8]>>(t: T) {
+            println!("{}", std::mem::size_of::<T>());
+            let _t: &[u8] = t.as_ref();
+        }
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        S::foo::<&[u8; 100]>(&a);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782_method_variant {
+    struct S;
+
+    impl S {
+        fn foo<T: AsRef<[u8]>>(&self, t: T) {
+            println!("{}", std::mem::size_of::<T>());
+            let _t: &[u8] = t.as_ref();
+        }
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        S.foo::<&[u8; 100]>(&a);
+    }
+}
diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs
index c93711ac8e2..7b97bcf3817 100644
--- a/tests/ui/needless_borrow.rs
+++ b/tests/ui/needless_borrow.rs
@@ -385,3 +385,128 @@ mod used_more_than_once {
     fn use_x(_: impl AsRef<str>) {}
     fn use_x_again(_: impl AsRef<str>) {}
 }
+
+// https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280
+#[allow(dead_code)]
+mod issue_9111 {
+    struct A;
+
+    impl Extend<u8> for A {
+        fn extend<T: IntoIterator<Item = u8>>(&mut self, _: T) {
+            unimplemented!()
+        }
+    }
+
+    impl<'a> Extend<&'a u8> for A {
+        fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, _: T) {
+            unimplemented!()
+        }
+    }
+
+    fn main() {
+        let mut a = A;
+        a.extend(&[]); // vs a.extend([]);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9710 {
+    fn main() {
+        let string = String::new();
+        for _i in 0..10 {
+            f(&string);
+        }
+    }
+
+    fn f<T: AsRef<str>>(_: T) {}
+}
+
+#[allow(dead_code)]
+mod issue_9739 {
+    fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
+
+    fn main() {
+        foo(if std::env::var_os("HI").is_some() {
+            &[0]
+        } else {
+            &[] as &[u32]
+        });
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9739_method_variant {
+    struct S;
+
+    impl S {
+        fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
+    }
+
+    fn main() {
+        S.foo(if std::env::var_os("HI").is_some() {
+            &[0]
+        } else {
+            &[] as &[u32]
+        });
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782 {
+    fn foo<T: AsRef<[u8]>>(t: T) {
+        println!("{}", std::mem::size_of::<T>());
+        let _t: &[u8] = t.as_ref();
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        // 100
+        foo::<[u8; 100]>(a);
+        foo(a);
+
+        // 16
+        foo::<&[u8]>(&a);
+        foo(a.as_slice());
+
+        // 8
+        foo::<&[u8; 100]>(&a);
+        foo(&a);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782_type_relative_variant {
+    struct S;
+
+    impl S {
+        fn foo<T: AsRef<[u8]>>(t: T) {
+            println!("{}", std::mem::size_of::<T>());
+            let _t: &[u8] = t.as_ref();
+        }
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        S::foo::<&[u8; 100]>(&a);
+    }
+}
+
+#[allow(dead_code)]
+mod issue_9782_method_variant {
+    struct S;
+
+    impl S {
+        fn foo<T: AsRef<[u8]>>(&self, t: T) {
+            println!("{}", std::mem::size_of::<T>());
+            let _t: &[u8] = t.as_ref();
+        }
+    }
+
+    fn main() {
+        let a: [u8; 100] = [0u8; 100];
+
+        S.foo::<&[u8; 100]>(&a);
+    }
+}
diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr
index 8b593268bec..485e6b84c86 100644
--- a/tests/ui/needless_borrow.stderr
+++ b/tests/ui/needless_borrow.stderr
@@ -210,5 +210,11 @@ error: the borrowed expression implements the required traits
 LL |         use_x(&x);
    |               ^^ help: change this to: `x`
 
-error: aborting due to 35 previous errors
+error: the borrowed expression implements the required traits
+  --> $DIR/needless_borrow.rs:474:13
+   |
+LL |         foo(&a);
+   |             ^^ help: change this to: `a`
+
+error: aborting due to 36 previous errors
 
diff --git a/tests/ui/needless_borrowed_ref.fixed b/tests/ui/needless_borrowed_ref.fixed
index bcb4eb2dd48..0c47ceb7b67 100644
--- a/tests/ui/needless_borrowed_ref.fixed
+++ b/tests/ui/needless_borrowed_ref.fixed
@@ -1,11 +1,32 @@
 // run-rustfix
 
 #![warn(clippy::needless_borrowed_reference)]
-#![allow(unused, clippy::needless_borrow)]
+#![allow(
+    unused,
+    irrefutable_let_patterns,
+    non_shorthand_field_patterns,
+    clippy::needless_borrow
+)]
 
 fn main() {}
 
-fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+struct Struct {
+    a: usize,
+    b: usize,
+    c: usize,
+}
+
+struct TupleStruct(u8, u8, u8);
+
+fn should_lint(
+    array: [u8; 4],
+    slice: &[u8],
+    slice_of_refs: &[&u8],
+    vec: Vec<u8>,
+    tuple: (u8, u8, u8),
+    tuple_struct: TupleStruct,
+    s: Struct,
+) {
     let mut v = Vec::<String>::new();
     let _ = v.iter_mut().filter(|a| a.is_empty());
 
@@ -24,16 +45,54 @@ fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>
     if let [a, b, ..] = slice {}
     if let [a, .., b] = slice {}
     if let [.., a, b] = slice {}
+
+    if let [a, _] = slice {}
+
+    if let (a, b, c) = &tuple {}
+    if let (a, _, c) = &tuple {}
+    if let (a, ..) = &tuple {}
+
+    if let TupleStruct(a, ..) = &tuple_struct {}
+
+    if let Struct {
+        a,
+        b: b,
+        c: renamed,
+    } = &s
+    {}
+
+    if let Struct { a, b: _, .. } = &s {}
 }
 
-fn should_not_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+fn should_not_lint(
+    array: [u8; 4],
+    slice: &[u8],
+    slice_of_refs: &[&u8],
+    vec: Vec<u8>,
+    tuple: (u8, u8, u8),
+    tuple_struct: TupleStruct,
+    s: Struct,
+) {
     if let [ref a] = slice {}
     if let &[ref a, b] = slice {}
     if let &[ref a, .., b] = slice {}
 
+    if let &(ref a, b, ..) = &tuple {}
+    if let &TupleStruct(ref a, b, ..) = &tuple_struct {}
+    if let &Struct { ref a, b, .. } = &s {}
+
     // must not be removed as variables must be bound consistently across | patterns
     if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
 
+    // the `&`s here technically could be removed, but it'd be noisy and without a `ref` doesn't match
+    // the lint name
+    if let &[] = slice {}
+    if let &[_] = slice {}
+    if let &[..] = slice {}
+    if let &(..) = &tuple {}
+    if let &TupleStruct(..) = &tuple_struct {}
+    if let &Struct { .. } = &s {}
+
     let mut var2 = 5;
     let thingy2 = Some(&mut var2);
     if let Some(&mut ref mut v) = thingy2 {
@@ -59,6 +118,6 @@ fn foo(a: &Animal, b: &Animal) {
         // lifetime mismatch error if there is no '&ref' before `feature(nll)` stabilization in 1.63
         (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
         //                  ^    and   ^ should **not** be linted
-        (&Animal::Dog(ref a), &Animal::Dog(_)) => (), //              ^ should **not** be linted
+        (Animal::Dog(a), &Animal::Dog(_)) => (),
     }
 }
diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs
index f6de1a6d83d..f883bb0c889 100644
--- a/tests/ui/needless_borrowed_ref.rs
+++ b/tests/ui/needless_borrowed_ref.rs
@@ -1,11 +1,32 @@
 // run-rustfix
 
 #![warn(clippy::needless_borrowed_reference)]
-#![allow(unused, clippy::needless_borrow)]
+#![allow(
+    unused,
+    irrefutable_let_patterns,
+    non_shorthand_field_patterns,
+    clippy::needless_borrow
+)]
 
 fn main() {}
 
-fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+struct Struct {
+    a: usize,
+    b: usize,
+    c: usize,
+}
+
+struct TupleStruct(u8, u8, u8);
+
+fn should_lint(
+    array: [u8; 4],
+    slice: &[u8],
+    slice_of_refs: &[&u8],
+    vec: Vec<u8>,
+    tuple: (u8, u8, u8),
+    tuple_struct: TupleStruct,
+    s: Struct,
+) {
     let mut v = Vec::<String>::new();
     let _ = v.iter_mut().filter(|&ref a| a.is_empty());
 
@@ -24,16 +45,54 @@ fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>
     if let &[ref a, ref b, ..] = slice {}
     if let &[ref a, .., ref b] = slice {}
     if let &[.., ref a, ref b] = slice {}
+
+    if let &[ref a, _] = slice {}
+
+    if let &(ref a, ref b, ref c) = &tuple {}
+    if let &(ref a, _, ref c) = &tuple {}
+    if let &(ref a, ..) = &tuple {}
+
+    if let &TupleStruct(ref a, ..) = &tuple_struct {}
+
+    if let &Struct {
+        ref a,
+        b: ref b,
+        c: ref renamed,
+    } = &s
+    {}
+
+    if let &Struct { ref a, b: _, .. } = &s {}
 }
 
-fn should_not_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+fn should_not_lint(
+    array: [u8; 4],
+    slice: &[u8],
+    slice_of_refs: &[&u8],
+    vec: Vec<u8>,
+    tuple: (u8, u8, u8),
+    tuple_struct: TupleStruct,
+    s: Struct,
+) {
     if let [ref a] = slice {}
     if let &[ref a, b] = slice {}
     if let &[ref a, .., b] = slice {}
 
+    if let &(ref a, b, ..) = &tuple {}
+    if let &TupleStruct(ref a, b, ..) = &tuple_struct {}
+    if let &Struct { ref a, b, .. } = &s {}
+
     // must not be removed as variables must be bound consistently across | patterns
     if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
 
+    // the `&`s here technically could be removed, but it'd be noisy and without a `ref` doesn't match
+    // the lint name
+    if let &[] = slice {}
+    if let &[_] = slice {}
+    if let &[..] = slice {}
+    if let &(..) = &tuple {}
+    if let &TupleStruct(..) = &tuple_struct {}
+    if let &Struct { .. } = &s {}
+
     let mut var2 = 5;
     let thingy2 = Some(&mut var2);
     if let Some(&mut ref mut v) = thingy2 {
@@ -59,6 +118,6 @@ fn foo(a: &Animal, b: &Animal) {
         // lifetime mismatch error if there is no '&ref' before `feature(nll)` stabilization in 1.63
         (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
         //                  ^    and   ^ should **not** be linted
-        (&Animal::Dog(ref a), &Animal::Dog(_)) => (), //              ^ should **not** be linted
+        (Animal::Dog(a), &Animal::Dog(_)) => (),
     }
 }
diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr
index 7453542e673..8d0f0c258dd 100644
--- a/tests/ui/needless_borrowed_ref.stderr
+++ b/tests/ui/needless_borrowed_ref.stderr
@@ -1,5 +1,5 @@
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:10:34
+  --> $DIR/needless_borrowed_ref.rs:31:34
    |
 LL |     let _ = v.iter_mut().filter(|&ref a| a.is_empty());
    |                                  ^^^^^^
@@ -12,7 +12,7 @@ LL +     let _ = v.iter_mut().filter(|a| a.is_empty());
    |
 
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:14:17
+  --> $DIR/needless_borrowed_ref.rs:35:17
    |
 LL |     if let Some(&ref v) = thingy {}
    |                 ^^^^^^
@@ -24,7 +24,7 @@ LL +     if let Some(v) = thingy {}
    |
 
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:16:14
+  --> $DIR/needless_borrowed_ref.rs:37:14
    |
 LL |     if let &[&ref a, ref b] = slice_of_refs {}
    |              ^^^^^^
@@ -36,7 +36,7 @@ LL +     if let &[a, ref b] = slice_of_refs {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:18:9
+  --> $DIR/needless_borrowed_ref.rs:39:9
    |
 LL |     let &[ref a, ..] = &array;
    |         ^^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL +     let [a, ..] = &array;
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:19:9
+  --> $DIR/needless_borrowed_ref.rs:40:9
    |
 LL |     let &[ref a, ref b, ..] = &array;
    |         ^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL +     let [a, b, ..] = &array;
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:21:12
+  --> $DIR/needless_borrowed_ref.rs:42:12
    |
 LL |     if let &[ref a, ref b] = slice {}
    |            ^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL +     if let [a, b] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:22:12
+  --> $DIR/needless_borrowed_ref.rs:43:12
    |
 LL |     if let &[ref a, ref b] = &vec[..] {}
    |            ^^^^^^^^^^^^^^^
@@ -84,7 +84,7 @@ LL +     if let [a, b] = &vec[..] {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:24:12
+  --> $DIR/needless_borrowed_ref.rs:45:12
    |
 LL |     if let &[ref a, ref b, ..] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL +     if let [a, b, ..] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:25:12
+  --> $DIR/needless_borrowed_ref.rs:46:12
    |
 LL |     if let &[ref a, .., ref b] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -108,7 +108,7 @@ LL +     if let [a, .., b] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:26:12
+  --> $DIR/needless_borrowed_ref.rs:47:12
    |
 LL |     if let &[.., ref a, ref b] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -119,5 +119,96 @@ LL -     if let &[.., ref a, ref b] = slice {}
 LL +     if let [.., a, b] = slice {}
    |
 
-error: aborting due to 10 previous errors
+error: dereferencing a slice pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:49:12
+   |
+LL |     if let &[ref a, _] = slice {}
+   |            ^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &[ref a, _] = slice {}
+LL +     if let [a, _] = slice {}
+   |
+
+error: dereferencing a tuple pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:51:12
+   |
+LL |     if let &(ref a, ref b, ref c) = &tuple {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &(ref a, ref b, ref c) = &tuple {}
+LL +     if let (a, b, c) = &tuple {}
+   |
+
+error: dereferencing a tuple pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:52:12
+   |
+LL |     if let &(ref a, _, ref c) = &tuple {}
+   |            ^^^^^^^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &(ref a, _, ref c) = &tuple {}
+LL +     if let (a, _, c) = &tuple {}
+   |
+
+error: dereferencing a tuple pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:53:12
+   |
+LL |     if let &(ref a, ..) = &tuple {}
+   |            ^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &(ref a, ..) = &tuple {}
+LL +     if let (a, ..) = &tuple {}
+   |
+
+error: dereferencing a tuple pattern where every element takes a reference
+  --> $DIR/needless_borrowed_ref.rs:55:12
+   |
+LL |     if let &TupleStruct(ref a, ..) = &tuple_struct {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &TupleStruct(ref a, ..) = &tuple_struct {}
+LL +     if let TupleStruct(a, ..) = &tuple_struct {}
+   |
+
+error: dereferencing a struct pattern where every field's pattern takes a reference
+  --> $DIR/needless_borrowed_ref.rs:57:12
+   |
+LL |       if let &Struct {
+   |  ____________^
+LL | |         ref a,
+LL | |         b: ref b,
+LL | |         c: ref renamed,
+LL | |     } = &s
+   | |_____^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL ~     if let Struct {
+LL ~         a,
+LL ~         b: b,
+LL ~         c: renamed,
+   |
+
+error: dereferencing a struct pattern where every field's pattern takes a reference
+  --> $DIR/needless_borrowed_ref.rs:64:12
+   |
+LL |     if let &Struct { ref a, b: _, .. } = &s {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try removing the `&` and `ref` parts
+   |
+LL -     if let &Struct { ref a, b: _, .. } = &s {}
+LL +     if let Struct { a, b: _, .. } = &s {}
+   |
+
+error: aborting due to 17 previous errors
 
diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed
index 6ecbbcb6249..2659ad38488 100644
--- a/tests/ui/needless_collect.fixed
+++ b/tests/ui/needless_collect.fixed
@@ -33,4 +33,33 @@ fn main() {
     // `BinaryHeap` doesn't have `contains` method
     sample.iter().count();
     sample.iter().next().is_none();
+
+    // Don't lint string from str
+    let _ = ["", ""].into_iter().collect::<String>().is_empty();
+
+    let _ = sample.iter().next().is_none();
+    let _ = sample.iter().any(|x| x == &0);
+
+    struct VecWrapper<T>(Vec<T>);
+    impl<T> core::ops::Deref for VecWrapper<T> {
+        type Target = Vec<T>;
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<T> IntoIterator for VecWrapper<T> {
+        type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
+        type Item = <Vec<T> as IntoIterator>::Item;
+        fn into_iter(self) -> Self::IntoIter {
+            self.0.into_iter()
+        }
+    }
+    impl<T> FromIterator<T> for VecWrapper<T> {
+        fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
+            Self(Vec::from_iter(iter))
+        }
+    }
+
+    let _ = sample.iter().next().is_none();
+    let _ = sample.iter().any(|x| x == &0);
 }
diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs
index 8dc69bcf5b3..535ec82982b 100644
--- a/tests/ui/needless_collect.rs
+++ b/tests/ui/needless_collect.rs
@@ -33,4 +33,33 @@ fn main() {
     // `BinaryHeap` doesn't have `contains` method
     sample.iter().collect::<BinaryHeap<_>>().len();
     sample.iter().collect::<BinaryHeap<_>>().is_empty();
+
+    // Don't lint string from str
+    let _ = ["", ""].into_iter().collect::<String>().is_empty();
+
+    let _ = sample.iter().collect::<HashSet<_>>().is_empty();
+    let _ = sample.iter().collect::<HashSet<_>>().contains(&&0);
+
+    struct VecWrapper<T>(Vec<T>);
+    impl<T> core::ops::Deref for VecWrapper<T> {
+        type Target = Vec<T>;
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<T> IntoIterator for VecWrapper<T> {
+        type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
+        type Item = <Vec<T> as IntoIterator>::Item;
+        fn into_iter(self) -> Self::IntoIter {
+            self.0.into_iter()
+        }
+    }
+    impl<T> FromIterator<T> for VecWrapper<T> {
+        fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
+            Self(Vec::from_iter(iter))
+        }
+    }
+
+    let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
+    let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
 }
diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr
index 039091627a8..584d2a1d835 100644
--- a/tests/ui/needless_collect.stderr
+++ b/tests/ui/needless_collect.stderr
@@ -66,5 +66,29 @@ error: avoid using `collect()` when not needed
 LL |     sample.iter().collect::<BinaryHeap<_>>().is_empty();
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`
 
-error: aborting due to 11 previous errors
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:40:27
+   |
+LL |     let _ = sample.iter().collect::<HashSet<_>>().is_empty();
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:41:27
+   |
+LL |     let _ = sample.iter().collect::<HashSet<_>>().contains(&&0);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:63:27
+   |
+LL |     let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:64:27
+   |
+LL |     let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`
+
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs
index 6d213b46c20..fe4209e99b2 100644
--- a/tests/ui/needless_collect_indirect.rs
+++ b/tests/ui/needless_collect_indirect.rs
@@ -1,4 +1,5 @@
 #![allow(clippy::uninlined_format_args)]
+#![warn(clippy::needless_collect)]
 
 use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
 
diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr
index 99e1b91d8fe..790d725907f 100644
--- a/tests/ui/needless_collect_indirect.stderr
+++ b/tests/ui/needless_collect_indirect.stderr
@@ -1,5 +1,5 @@
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:7:39
+  --> $DIR/needless_collect_indirect.rs:8:39
    |
 LL |     let indirect_iter = sample.iter().collect::<Vec<_>>();
    |                                       ^^^^^^^
@@ -14,7 +14,7 @@ LL ~     sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:9:38
+  --> $DIR/needless_collect_indirect.rs:10:38
    |
 LL |     let indirect_len = sample.iter().collect::<VecDeque<_>>();
    |                                      ^^^^^^^
@@ -28,7 +28,7 @@ LL ~     sample.iter().count();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:11:40
+  --> $DIR/needless_collect_indirect.rs:12:40
    |
 LL |     let indirect_empty = sample.iter().collect::<VecDeque<_>>();
    |                                        ^^^^^^^
@@ -42,7 +42,7 @@ LL ~     sample.iter().next().is_none();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:13:43
+  --> $DIR/needless_collect_indirect.rs:14:43
    |
 LL |     let indirect_contains = sample.iter().collect::<VecDeque<_>>();
    |                                           ^^^^^^^
@@ -56,7 +56,7 @@ LL ~     sample.iter().any(|x| x == &5);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:25:48
+  --> $DIR/needless_collect_indirect.rs:26:48
    |
 LL |     let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
    |                                                ^^^^^^^
@@ -70,7 +70,7 @@ LL ~     sample.into_iter().any(|x| x == a);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:54:51
+  --> $DIR/needless_collect_indirect.rs:55:51
    |
 LL |         let buffer: Vec<&str> = string.split('/').collect();
    |                                                   ^^^^^^^
@@ -84,7 +84,7 @@ LL ~         string.split('/').count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:59:55
+  --> $DIR/needless_collect_indirect.rs:60:55
    |
 LL |         let indirect_len: VecDeque<_> = sample.iter().collect();
    |                                                       ^^^^^^^
@@ -98,7 +98,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:64:57
+  --> $DIR/needless_collect_indirect.rs:65:57
    |
 LL |         let indirect_len: LinkedList<_> = sample.iter().collect();
    |                                                         ^^^^^^^
@@ -112,7 +112,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:69:57
+  --> $DIR/needless_collect_indirect.rs:70:57
    |
 LL |         let indirect_len: BinaryHeap<_> = sample.iter().collect();
    |                                                         ^^^^^^^
@@ -126,7 +126,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:129:59
+  --> $DIR/needless_collect_indirect.rs:130:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -143,7 +143,7 @@ LL ~             vec.iter().map(|k| k * k).any(|x| x == i);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:154:59
+  --> $DIR/needless_collect_indirect.rs:155:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -160,7 +160,7 @@ LL ~             vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:183:63
+  --> $DIR/needless_collect_indirect.rs:184:63
    |
 LL |                 let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                               ^^^^^^^
@@ -177,7 +177,7 @@ LL ~                 vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:219:59
+  --> $DIR/needless_collect_indirect.rs:220:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -195,7 +195,7 @@ LL ~                 vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:244:26
+  --> $DIR/needless_collect_indirect.rs:245:26
    |
 LL |         let w = v.iter().collect::<Vec<_>>();
    |                          ^^^^^^^
@@ -211,7 +211,7 @@ LL ~         for _ in 0..v.iter().count() {
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:266:30
+  --> $DIR/needless_collect_indirect.rs:267:30
    |
 LL |         let mut w = v.iter().collect::<Vec<_>>();
    |                              ^^^^^^^
@@ -227,7 +227,7 @@ LL ~         while 1 == v.iter().count() {
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:288:30
+  --> $DIR/needless_collect_indirect.rs:289:30
    |
 LL |         let mut w = v.iter().collect::<Vec<_>>();
    |                              ^^^^^^^
diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs
index fc686b1dac0..2efc936752e 100644
--- a/tests/ui/needless_lifetimes.rs
+++ b/tests/ui/needless_lifetimes.rs
@@ -29,11 +29,20 @@ fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
     x
 }
 
-// No error; multiple input refs.
-fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8
+//                                                ^^^
+fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
     x
 }
 
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8
+//                                     ^^^
+fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
+    y
+}
+
 // No error; multiple input refs
 async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
     args.get(0).cloned()
@@ -44,11 +53,20 @@ fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
     x
 }
 
-// No error.
-fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()>
+//                                           ^^^
+fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
     Ok(x)
 }
 
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()>
+//                                ^^^
+fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
+    Ok(y)
+}
+
 // No error; two input refs.
 fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
     x.unwrap()
@@ -129,11 +147,20 @@ impl X {
         &self.x
     }
 
-    // No error; multiple input refs.
-    fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
+    // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+    //   fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8
+    //                                          ^^^
+    fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
         &self.x
     }
 
+    // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+    //   fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8
+    //                            ^^^^^
+    fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
+        x
+    }
+
     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
 
     // No error; same lifetimes on two params.
@@ -167,8 +194,19 @@ fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
     unimplemented!()
 }
 
-// No warning; two input lifetimes.
-fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str
+//                                         ^^
+fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+    unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str
+//                                 ^^^^
+fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
     unimplemented!()
 }
 
@@ -203,8 +241,19 @@ fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
     unimplemented!()
 }
 
-// No warning; two input lifetimes.
-fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str
+//                                             ^^
+fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+    unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str
+//                                ^^^^^^^^^
+fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
     unimplemented!()
 }
 
@@ -419,4 +468,31 @@ mod issue7296 {
     }
 }
 
+mod pr_9743_false_negative_fix {
+    #![allow(unused)]
+
+    fn foo<'a>(x: &'a u8, y: &'_ u8) {}
+
+    fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
+}
+
+mod pr_9743_output_lifetime_checks {
+    #![allow(unused)]
+
+    // lint: only one input
+    fn one_input<'a>(x: &'a u8) -> &'a u8 {
+        unimplemented!()
+    }
+
+    // lint: multiple inputs, output would not be elided
+    fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+        unimplemented!()
+    }
+
+    // don't lint: multiple inputs, output would be elided (which would create an ambiguity)
+    fn multiple_inputs_output_would_be_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'a u8 {
+        unimplemented!()
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr
index 3c428fd4674..5a7cf13c86d 100644
--- a/tests/ui/needless_lifetimes.stderr
+++ b/tests/ui/needless_lifetimes.stderr
@@ -1,4 +1,4 @@
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a, 'b
   --> $DIR/needless_lifetimes.rs:11:1
    |
 LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
@@ -6,185 +6,311 @@ LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a, 'b
   --> $DIR/needless_lifetimes.rs:13:1
    |
 LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+error: the following explicit lifetimes could be elided: 'a
   --> $DIR/needless_lifetimes.rs:23:1
    |
 LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:57:1
+error: the following explicit lifetimes could be elided: 'b
+  --> $DIR/needless_lifetimes.rs:35:1
+   |
+LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:42:1
+   |
+LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'b
+  --> $DIR/needless_lifetimes.rs:59:1
+   |
+LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:66:1
+   |
+LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:75:1
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:62:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:80:1
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:74:1
+error: the following explicit lifetimes could be elided: 'a, 'b
+  --> $DIR/needless_lifetimes.rs:92:1
    |
 LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:92:37
+   |
+LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
+   |                                     ^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:98:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:116:1
    |
 LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:116:32
+   |
+LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
+   |                                ^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:128:5
+error: the following explicit lifetimes could be elided: 's
+  --> $DIR/needless_lifetimes.rs:146:5
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:137:5
+error: the following explicit lifetimes could be elided: 't
+  --> $DIR/needless_lifetimes.rs:153:5
+   |
+LL |     fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 's
+  --> $DIR/needless_lifetimes.rs:160:5
+   |
+LL |     fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 's, 't
+  --> $DIR/needless_lifetimes.rs:164:5
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:156:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:183:1
    |
 LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:183:33
+   |
+LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
+   |                                 ^^
+
+error: the following explicit lifetimes could be elided: 'b
+  --> $DIR/needless_lifetimes.rs:201:1
+   |
+LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:201:43
+   |
+LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+   |                                           ^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:209:1
+   |
+LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:186:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:224:1
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:192:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:230:1
    |
 LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:230:37
+   |
+LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
+   |                                     ^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:211:1
+error: the following explicit lifetimes could be elided: 'b
+  --> $DIR/needless_lifetimes.rs:248:1
+   |
+LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:248:47
+   |
+LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+   |                                               ^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:256:1
+   |
+LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:260:1
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:219:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:268:1
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:255:1
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:304:1
    |
 LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace with `'_` in generic arguments such as here
+  --> $DIR/needless_lifetimes.rs:304:47
+   |
+LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
+   |                                               ^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:262:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:311:9
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:266:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:315:9
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:279:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:328:9
    |
 LL |         fn baz<'a>(&'a self) -> impl Foo + 'a {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:311:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:360:5
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:320:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:369:5
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:332:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:381:5
    |
 LL |     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:347:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:396:5
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:360:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:409:5
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:363:5
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:412:5
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:385:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:434:9
    |
 LL |         fn implicit<'a>(&'a self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:388:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:437:9
    |
 LL |         fn implicit_mut<'a>(&'a mut self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:399:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:448:9
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:405:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:454:9
    |
 LL |         fn implicit<'a>(&'a self) -> &'a ();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:406:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:455:9
    |
 LL |         fn implicit_provided<'a>(&'a self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:415:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:464:9
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:416:9
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:465:9
    |
 LL |         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 31 previous errors
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:474:5
+   |
+LL |     fn foo<'a>(x: &'a u8, y: &'_ u8) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:476:5
+   |
+LL |     fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:483:5
+   |
+LL |     fn one_input<'a>(x: &'a u8) -> &'a u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:488:5
+   |
+LL |     fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 45 previous errors
 
diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs
index 3dbef19890e..28e8f459d44 100644
--- a/tests/ui/never_loop.rs
+++ b/tests/ui/never_loop.rs
@@ -229,6 +229,27 @@ pub fn test18() {
     };
 }
 
+// Issue #9831: unconditional break to internal labeled block
+pub fn test19() {
+    fn thing(iter: impl Iterator) {
+        for _ in iter {
+            'b: {
+                break 'b;
+            }
+        }
+    }
+}
+
+pub fn test20() {
+    'a: loop {
+        'b: {
+            break 'b 'c: {
+                break 'a;
+            };
+        }
+    }
+}
+
 fn main() {
     test1();
     test2();
diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr
index 3033f019244..b7029bf8bed 100644
--- a/tests/ui/never_loop.stderr
+++ b/tests/ui/never_loop.stderr
@@ -114,5 +114,17 @@ LL | |         break x;
 LL | |     };
    | |_____^
 
-error: aborting due to 10 previous errors
+error: this loop never actually loops
+  --> $DIR/never_loop.rs:244:5
+   |
+LL | /     'a: loop {
+LL | |         'b: {
+LL | |             break 'b 'c: {
+LL | |                 break 'a;
+LL | |             };
+LL | |         }
+LL | |     }
+   | |_____^
+
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs
index 2f315ffe298..f69982d63a8 100644
--- a/tests/ui/new_ret_no_self.rs
+++ b/tests/ui/new_ret_no_self.rs
@@ -350,3 +350,53 @@ impl RetOtherSelf<T> {
         RetOtherSelf(RetOtherSelfWrapper(t))
     }
 }
+
+mod issue7344 {
+    struct RetImplTraitSelf<T>(T);
+
+    impl<T> RetImplTraitSelf<T> {
+        // should not trigger lint
+        fn new(t: T) -> impl Into<Self> {
+            Self(t)
+        }
+    }
+
+    struct RetImplTraitNoSelf<T>(T);
+
+    impl<T> RetImplTraitNoSelf<T> {
+        // should trigger lint
+        fn new(t: T) -> impl Into<i32> {
+            1
+        }
+    }
+
+    trait Trait2<T, U> {}
+    impl<T, U> Trait2<T, U> for () {}
+
+    struct RetImplTraitSelf2<T>(T);
+
+    impl<T> RetImplTraitSelf2<T> {
+        // should not trigger lint
+        fn new(t: T) -> impl Trait2<(), Self> {
+            unimplemented!()
+        }
+    }
+
+    struct RetImplTraitNoSelf2<T>(T);
+
+    impl<T> RetImplTraitNoSelf2<T> {
+        // should trigger lint
+        fn new(t: T) -> impl Trait2<(), i32> {
+            unimplemented!()
+        }
+    }
+
+    struct RetImplTraitSelfAdt<'a>(&'a str);
+
+    impl<'a> RetImplTraitSelfAdt<'a> {
+        // should not trigger lint
+        fn new<'b: 'a>(s: &'b str) -> impl Into<RetImplTraitSelfAdt<'b>> {
+            RetImplTraitSelfAdt(s)
+        }
+    }
+}
diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr
index 8217bc6187f..bc13be47927 100644
--- a/tests/ui/new_ret_no_self.stderr
+++ b/tests/ui/new_ret_no_self.stderr
@@ -76,5 +76,21 @@ LL | |             unimplemented!();
 LL | |         }
    | |_________^
 
-error: aborting due to 10 previous errors
+error: methods called `new` usually return `Self`
+  --> $DIR/new_ret_no_self.rs:368:9
+   |
+LL | /         fn new(t: T) -> impl Into<i32> {
+LL | |             1
+LL | |         }
+   | |_________^
+
+error: methods called `new` usually return `Self`
+  --> $DIR/new_ret_no_self.rs:389:9
+   |
+LL | /         fn new(t: T) -> impl Trait2<(), i32> {
+LL | |             unimplemented!()
+LL | |         }
+   | |_________^
+
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed
index f15ac551bb3..0456005dce4 100644
--- a/tests/ui/option_if_let_else.fixed
+++ b/tests/ui/option_if_let_else.fixed
@@ -189,3 +189,12 @@ fn main() {
     let _ = res.map_or(1, |a| a + 1);
     let _ = res.map_or(5, |a| a + 1);
 }
+
+#[allow(dead_code)]
+fn issue9742() -> Option<&'static str> {
+    // should not lint because of guards
+    match Some("foo  ") {
+        Some(name) if name.starts_with("foo") => Some(name.trim()),
+        _ => None,
+    }
+}
diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs
index 9eeaea12d3b..23b148752cb 100644
--- a/tests/ui/option_if_let_else.rs
+++ b/tests/ui/option_if_let_else.rs
@@ -230,3 +230,12 @@ fn main() {
     };
     let _ = if let Ok(a) = res { a + 1 } else { 5 };
 }
+
+#[allow(dead_code)]
+fn issue9742() -> Option<&'static str> {
+    // should not lint because of guards
+    match Some("foo  ") {
+        Some(name) if name.starts_with("foo") => Some(name.trim()),
+        _ => None,
+    }
+}
diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed
index 23b1aa8bebd..be9a65506e1 100644
--- a/tests/ui/or_fun_call.fixed
+++ b/tests/ui/or_fun_call.fixed
@@ -236,4 +236,20 @@ mod issue9608 {
     }
 }
 
+mod issue8993 {
+    fn g() -> i32 {
+        3
+    }
+
+    fn f(n: i32) -> i32 {
+        n
+    }
+
+    fn test_map_or() {
+        let _ = Some(4).map_or_else(g, |v| v);
+        let _ = Some(4).map_or_else(g, f);
+        let _ = Some(4).map_or(0, f);
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs
index 039998f22dd..628c9704638 100644
--- a/tests/ui/or_fun_call.rs
+++ b/tests/ui/or_fun_call.rs
@@ -236,4 +236,20 @@ mod issue9608 {
     }
 }
 
+mod issue8993 {
+    fn g() -> i32 {
+        3
+    }
+
+    fn f(n: i32) -> i32 {
+        n
+    }
+
+    fn test_map_or() {
+        let _ = Some(4).map_or(g(), |v| v);
+        let _ = Some(4).map_or(g(), f);
+        let _ = Some(4).map_or(0, f);
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr
index 113ba150c61..ba3001db7a5 100644
--- a/tests/ui/or_fun_call.stderr
+++ b/tests/ui/or_fun_call.stderr
@@ -156,5 +156,17 @@ error: use of `unwrap_or` followed by a call to `new`
 LL |         .unwrap_or(String::new());
    |          ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
-error: aborting due to 26 previous errors
+error: use of `map_or` followed by a function call
+  --> $DIR/or_fun_call.rs:249:25
+   |
+LL |         let _ = Some(4).map_or(g(), |v| v);
+   |                         ^^^^^^^^^^^^^^^^^^ help: try this: `map_or_else(g, |v| v)`
+
+error: use of `map_or` followed by a function call
+  --> $DIR/or_fun_call.rs:250:25
+   |
+LL |         let _ = Some(4).map_or(g(), f);
+   |                         ^^^^^^^^^^^^^^ help: try this: `map_or_else(g, f)`
+
+error: aborting due to 28 previous errors
 
diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed
index 993389232cc..5c49d46da72 100644
--- a/tests/ui/question_mark.fixed
+++ b/tests/ui/question_mark.fixed
@@ -134,6 +134,9 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
         return func_returning_result();
     }
 
+    // no warning
+    let _ = if let Err(e) = x { Err(e) } else { Ok(0) };
+
     Ok(y)
 }
 
diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs
index 9ae0d88829a..d057df6a9b3 100644
--- a/tests/ui/question_mark.rs
+++ b/tests/ui/question_mark.rs
@@ -166,6 +166,9 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
         return func_returning_result();
     }
 
+    // no warning
+    let _ = if let Err(e) = x { Err(e) } else { Ok(0) };
+
     Ok(y)
 }
 
diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr
index 1b6cd524b2f..23172d7e535 100644
--- a/tests/ui/question_mark.stderr
+++ b/tests/ui/question_mark.stderr
@@ -115,7 +115,7 @@ LL | |     }
    | |_____^ help: replace it with: `x?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:193:5
+  --> $DIR/question_mark.rs:196:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
@@ -123,7 +123,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:200:5
+  --> $DIR/question_mark.rs:203:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed
index 8beae8dee08..689928f0479 100644
--- a/tests/ui/rename.fixed
+++ b/tests/ui/rename.fixed
@@ -12,7 +12,6 @@
 #![allow(clippy::disallowed_methods)]
 #![allow(clippy::disallowed_types)]
 #![allow(clippy::mixed_read_write_in_expression)]
-#![allow(for_loops_over_fallibles)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
 #![allow(clippy::overly_complex_bool_expr)]
@@ -27,9 +26,11 @@
 #![allow(clippy::recursive_format_impl)]
 #![allow(clippy::invisible_characters)]
 #![allow(drop_bounds)]
+#![allow(for_loops_over_fallibles)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
+#![allow(let_underscore_drop)]
 #![allow(enum_intrinsics_non_enums)]
 #![allow(non_fmt_panics)]
 #![allow(named_arguments_used_positionally)]
@@ -45,8 +46,6 @@
 #![warn(clippy::disallowed_methods)]
 #![warn(clippy::disallowed_types)]
 #![warn(clippy::mixed_read_write_in_expression)]
-#![warn(for_loops_over_fallibles)]
-#![warn(for_loops_over_fallibles)]
 #![warn(clippy::useless_conversion)]
 #![warn(clippy::match_result_ok)]
 #![warn(clippy::overly_complex_bool_expr)]
@@ -66,9 +65,12 @@
 #![warn(clippy::invisible_characters)]
 #![warn(drop_bounds)]
 #![warn(for_loops_over_fallibles)]
+#![warn(for_loops_over_fallibles)]
+#![warn(for_loops_over_fallibles)]
 #![warn(array_into_iter)]
 #![warn(invalid_atomic_ordering)]
 #![warn(invalid_value)]
+#![warn(let_underscore_drop)]
 #![warn(enum_intrinsics_non_enums)]
 #![warn(non_fmt_panics)]
 #![warn(named_arguments_used_positionally)]
diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs
index 9e665047baa..b74aa650ffd 100644
--- a/tests/ui/rename.rs
+++ b/tests/ui/rename.rs
@@ -12,7 +12,6 @@
 #![allow(clippy::disallowed_methods)]
 #![allow(clippy::disallowed_types)]
 #![allow(clippy::mixed_read_write_in_expression)]
-#![allow(for_loops_over_fallibles)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
 #![allow(clippy::overly_complex_bool_expr)]
@@ -27,9 +26,11 @@
 #![allow(clippy::recursive_format_impl)]
 #![allow(clippy::invisible_characters)]
 #![allow(drop_bounds)]
+#![allow(for_loops_over_fallibles)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
+#![allow(let_underscore_drop)]
 #![allow(enum_intrinsics_non_enums)]
 #![allow(non_fmt_panics)]
 #![allow(named_arguments_used_positionally)]
@@ -45,8 +46,6 @@
 #![warn(clippy::disallowed_method)]
 #![warn(clippy::disallowed_type)]
 #![warn(clippy::eval_order_dependence)]
-#![warn(clippy::for_loop_over_option)]
-#![warn(clippy::for_loop_over_result)]
 #![warn(clippy::identity_conversion)]
 #![warn(clippy::if_let_some_result)]
 #![warn(clippy::logic_bug)]
@@ -65,10 +64,13 @@
 #![warn(clippy::to_string_in_display)]
 #![warn(clippy::zero_width_space)]
 #![warn(clippy::drop_bounds)]
+#![warn(clippy::for_loop_over_option)]
+#![warn(clippy::for_loop_over_result)]
 #![warn(clippy::for_loops_over_fallibles)]
 #![warn(clippy::into_iter_on_array)]
 #![warn(clippy::invalid_atomic_ordering)]
 #![warn(clippy::invalid_ref)]
+#![warn(clippy::let_underscore_drop)]
 #![warn(clippy::mem_discriminant_non_enum)]
 #![warn(clippy::panic_params)]
 #![warn(clippy::positional_named_format_parameters)]
diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr
index 63eb565185f..622a32c5908 100644
--- a/tests/ui/rename.stderr
+++ b/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:39:9
+  --> $DIR/rename.rs:40:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
@@ -7,232 +7,238 @@ LL | #![warn(clippy::blacklisted_name)]
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:40:9
+  --> $DIR/rename.rs:41:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:41:9
+  --> $DIR/rename.rs:42:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:42:9
+  --> $DIR/rename.rs:43:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:43:9
+  --> $DIR/rename.rs:44:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:44:9
+  --> $DIR/rename.rs:45:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:45:9
+  --> $DIR/rename.rs:46:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:46:9
+  --> $DIR/rename.rs:47:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:47:9
+  --> $DIR/rename.rs:48:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
-error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:48:9
-   |
-LL | #![warn(clippy::for_loop_over_option)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
-
-error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:49:9
-   |
-LL | #![warn(clippy::for_loop_over_result)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
-
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:50:9
+  --> $DIR/rename.rs:49:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:51:9
+  --> $DIR/rename.rs:50:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:51:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:52:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
-error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
+error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
+  --> $DIR/rename.rs:67:9
+   |
+LL | #![warn(clippy::for_loop_over_option)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
+
+error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
   --> $DIR/rename.rs:68:9
    |
+LL | #![warn(clippy::for_loop_over_result)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
+
+error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
+  --> $DIR/rename.rs:69:9
+   |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
+error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
+  --> $DIR/rename.rs:73:9
+   |
+LL | #![warn(clippy::let_underscore_drop)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
+
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 39 previous errors
+error: aborting due to 40 previous errors
 
diff --git a/tests/ui/result_large_err.rs b/tests/ui/result_large_err.rs
index f7df3b85655..9dd27d6dc01 100644
--- a/tests/ui/result_large_err.rs
+++ b/tests/ui/result_large_err.rs
@@ -50,6 +50,18 @@ impl LargeErrorVariants<()> {
     }
 }
 
+enum MultipleLargeVariants {
+    _Biggest([u8; 1024]),
+    _AlsoBig([u8; 512]),
+    _Ok(usize),
+}
+
+impl MultipleLargeVariants {
+    fn large_enum_error() -> Result<(), Self> {
+        Ok(())
+    }
+}
+
 trait TraitForcesLargeError {
     fn large_error() -> Result<(), [u8; 512]> {
         Ok(())
diff --git a/tests/ui/result_large_err.stderr b/tests/ui/result_large_err.stderr
index bea101fe20b..c386edfd215 100644
--- a/tests/ui/result_large_err.stderr
+++ b/tests/ui/result_large_err.stderr
@@ -42,13 +42,29 @@ LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeErro
 error: the `Err`-variant returned from this function is very large
   --> $DIR/result_large_err.rs:48:34
    |
+LL |     _Omg([u8; 512]),
+   |     --------------- the largest variant contains at least 512 bytes
+...
 LL |     pub fn large_enum_error() -> Result<(), Self> {
-   |                                  ^^^^^^^^^^^^^^^^ the `Err`-variant is at least 513 bytes
+   |                                  ^^^^^^^^^^^^^^^^
    |
    = help: try reducing the size of `LargeErrorVariants<()>`, for example by boxing large elements or replacing it with `Box<LargeErrorVariants<()>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:54:25
+  --> $DIR/result_large_err.rs:60:30
+   |
+LL |     _Biggest([u8; 1024]),
+   |     -------------------- the largest variant contains at least 1024 bytes
+LL |     _AlsoBig([u8; 512]),
+   |     ------------------- the variant `_AlsoBig` contains at least 512 bytes
+...
+LL |     fn large_enum_error() -> Result<(), Self> {
+   |                              ^^^^^^^^^^^^^^^^
+   |
+   = help: try reducing the size of `MultipleLargeVariants`, for example by boxing large elements or replacing it with `Box<MultipleLargeVariants>`
+
+error: the `Err`-variant returned from this function is very large
+  --> $DIR/result_large_err.rs:66:25
    |
 LL |     fn large_error() -> Result<(), [u8; 512]> {
    |                         ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -56,7 +72,7 @@ LL |     fn large_error() -> Result<(), [u8; 512]> {
    = help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:73:29
+  --> $DIR/result_large_err.rs:85:29
    |
 LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> {
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -64,7 +80,7 @@ LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> {
    = help: try reducing the size of `FullyDefinedUnionError`, for example by boxing large elements or replacing it with `Box<FullyDefinedUnionError>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:82:40
+  --> $DIR/result_large_err.rs:94:40
    |
 LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@@ -72,7 +88,7 @@ LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
    = help: try reducing the size of `UnionError<T>`, for example by boxing large elements or replacing it with `Box<UnionError<T>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:91:34
+  --> $DIR/result_large_err.rs:103:34
    |
 LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes
@@ -80,12 +96,12 @@ LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> {
    = help: try reducing the size of `ArrayError<i32, U>`, for example by boxing large elements or replacing it with `Box<ArrayError<i32, U>>`
 
 error: the `Err`-variant returned from this function is very large
-  --> $DIR/result_large_err.rs:95:31
+  --> $DIR/result_large_err.rs:107:31
    |
 LL | pub fn array_error<T, U>() -> Result<(), ArrayError<(i32, T), U>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes
    |
    = help: try reducing the size of `ArrayError<(i32, T), U>`, for example by boxing large elements or replacing it with `Box<ArrayError<(i32, T), U>>`
 
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/seek_from_current.fixed b/tests/ui/seek_from_current.fixed
new file mode 100644
index 00000000000..4b5303324bc
--- /dev/null
+++ b/tests/ui/seek_from_current.fixed
@@ -0,0 +1,26 @@
+// run-rustfix
+#![warn(clippy::seek_from_current)]
+#![feature(custom_inner_attributes)]
+
+use std::fs::File;
+use std::io::{self, Seek, SeekFrom, Write};
+
+fn _msrv_1_50() -> io::Result<()> {
+    #![clippy::msrv = "1.50"]
+    let mut f = File::create("foo.txt")?;
+    f.write_all(b"Hi!")?;
+    f.seek(SeekFrom::Current(0))?;
+    f.seek(SeekFrom::Current(1))?;
+    Ok(())
+}
+
+fn _msrv_1_51() -> io::Result<()> {
+    #![clippy::msrv = "1.51"]
+    let mut f = File::create("foo.txt")?;
+    f.write_all(b"Hi!")?;
+    f.stream_position()?;
+    f.seek(SeekFrom::Current(1))?;
+    Ok(())
+}
+
+fn main() {}
diff --git a/tests/ui/seek_from_current.rs b/tests/ui/seek_from_current.rs
new file mode 100644
index 00000000000..f93639261a1
--- /dev/null
+++ b/tests/ui/seek_from_current.rs
@@ -0,0 +1,26 @@
+// run-rustfix
+#![warn(clippy::seek_from_current)]
+#![feature(custom_inner_attributes)]
+
+use std::fs::File;
+use std::io::{self, Seek, SeekFrom, Write};
+
+fn _msrv_1_50() -> io::Result<()> {
+    #![clippy::msrv = "1.50"]
+    let mut f = File::create("foo.txt")?;
+    f.write_all(b"Hi!")?;
+    f.seek(SeekFrom::Current(0))?;
+    f.seek(SeekFrom::Current(1))?;
+    Ok(())
+}
+
+fn _msrv_1_51() -> io::Result<()> {
+    #![clippy::msrv = "1.51"]
+    let mut f = File::create("foo.txt")?;
+    f.write_all(b"Hi!")?;
+    f.seek(SeekFrom::Current(0))?;
+    f.seek(SeekFrom::Current(1))?;
+    Ok(())
+}
+
+fn main() {}
diff --git a/tests/ui/seek_from_current.stderr b/tests/ui/seek_from_current.stderr
new file mode 100644
index 00000000000..db1125b53cd
--- /dev/null
+++ b/tests/ui/seek_from_current.stderr
@@ -0,0 +1,10 @@
+error: using `SeekFrom::Current` to start from current position
+  --> $DIR/seek_from_current.rs:21:5
+   |
+LL |     f.seek(SeekFrom::Current(0))?;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `f.stream_position()`
+   |
+   = note: `-D clippy::seek-from-current` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/seek_to_start_instead_of_rewind.fixed b/tests/ui/seek_to_start_instead_of_rewind.fixed
new file mode 100644
index 00000000000..464b6cdef63
--- /dev/null
+++ b/tests/ui/seek_to_start_instead_of_rewind.fixed
@@ -0,0 +1,137 @@
+// run-rustfix
+#![allow(unused)]
+#![feature(custom_inner_attributes)]
+#![warn(clippy::seek_to_start_instead_of_rewind)]
+
+use std::fs::OpenOptions;
+use std::io::{Read, Seek, SeekFrom, Write};
+
+struct StructWithSeekMethod {}
+
+impl StructWithSeekMethod {
+    fn seek(&mut self, from: SeekFrom) {}
+}
+
+trait MySeekTrait {
+    fn seek(&mut self, from: SeekFrom) {}
+}
+
+struct StructWithSeekTrait {}
+impl MySeekTrait for StructWithSeekTrait {}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait_bound<T: MySeekTrait>(t: &mut T) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should trigger clippy warning
+fn seek_to_start<T: Seek>(t: &mut T) {
+    t.rewind();
+}
+
+// This should trigger clippy warning
+fn owned_seek_to_start<T: Seek>(mut t: T) {
+    t.rewind();
+}
+
+// This should NOT trigger clippy warning because
+// it does not seek to start
+fn seek_to_5<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::Start(5));
+}
+
+// This should NOT trigger clippy warning because
+// it does not seek to start
+fn seek_to_end<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::End(0));
+}
+
+fn main() {
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let mut my_struct_trait = StructWithSeekTrait {};
+    seek_to_start_false_trait_bound(&mut my_struct_trait);
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+    seek_to_5(&mut f);
+    seek_to_end(&mut f);
+    seek_to_start(&mut f);
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
+
+fn msrv_1_54() {
+    #![clippy::msrv = "1.54"]
+
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+
+    f.seek(SeekFrom::Start(0));
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
+
+fn msrv_1_55() {
+    #![clippy::msrv = "1.55"]
+
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+
+    f.rewind();
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
diff --git a/tests/ui/seek_to_start_instead_of_rewind.rs b/tests/ui/seek_to_start_instead_of_rewind.rs
new file mode 100644
index 00000000000..68e09bd7c1f
--- /dev/null
+++ b/tests/ui/seek_to_start_instead_of_rewind.rs
@@ -0,0 +1,137 @@
+// run-rustfix
+#![allow(unused)]
+#![feature(custom_inner_attributes)]
+#![warn(clippy::seek_to_start_instead_of_rewind)]
+
+use std::fs::OpenOptions;
+use std::io::{Read, Seek, SeekFrom, Write};
+
+struct StructWithSeekMethod {}
+
+impl StructWithSeekMethod {
+    fn seek(&mut self, from: SeekFrom) {}
+}
+
+trait MySeekTrait {
+    fn seek(&mut self, from: SeekFrom) {}
+}
+
+struct StructWithSeekTrait {}
+impl MySeekTrait for StructWithSeekTrait {}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// StructWithSeekMethod does not implement std::io::Seek;
+fn seek_to_start_false_trait_bound<T: MySeekTrait>(t: &mut T) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should trigger clippy warning
+fn seek_to_start<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should trigger clippy warning
+fn owned_seek_to_start<T: Seek>(mut t: T) {
+    t.seek(SeekFrom::Start(0));
+}
+
+// This should NOT trigger clippy warning because
+// it does not seek to start
+fn seek_to_5<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::Start(5));
+}
+
+// This should NOT trigger clippy warning because
+// it does not seek to start
+fn seek_to_end<T: Seek>(t: &mut T) {
+    t.seek(SeekFrom::End(0));
+}
+
+fn main() {
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let mut my_struct_trait = StructWithSeekTrait {};
+    seek_to_start_false_trait_bound(&mut my_struct_trait);
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+    seek_to_5(&mut f);
+    seek_to_end(&mut f);
+    seek_to_start(&mut f);
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
+
+fn msrv_1_54() {
+    #![clippy::msrv = "1.54"]
+
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+
+    f.seek(SeekFrom::Start(0));
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
+
+fn msrv_1_55() {
+    #![clippy::msrv = "1.55"]
+
+    let mut f = OpenOptions::new()
+        .write(true)
+        .read(true)
+        .create(true)
+        .open("foo.txt")
+        .unwrap();
+
+    let hello = "Hello!\n";
+    write!(f, "{hello}").unwrap();
+
+    f.seek(SeekFrom::Start(0));
+
+    let mut buf = String::new();
+    f.read_to_string(&mut buf).unwrap();
+
+    assert_eq!(&buf, hello);
+}
diff --git a/tests/ui/seek_to_start_instead_of_rewind.stderr b/tests/ui/seek_to_start_instead_of_rewind.stderr
new file mode 100644
index 00000000000..de0eec5d909
--- /dev/null
+++ b/tests/ui/seek_to_start_instead_of_rewind.stderr
@@ -0,0 +1,22 @@
+error: used `seek` to go to the start of the stream
+  --> $DIR/seek_to_start_instead_of_rewind.rs:54:7
+   |
+LL |     t.seek(SeekFrom::Start(0));
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
+   |
+   = note: `-D clippy::seek-to-start-instead-of-rewind` implied by `-D warnings`
+
+error: used `seek` to go to the start of the stream
+  --> $DIR/seek_to_start_instead_of_rewind.rs:59:7
+   |
+LL |     t.seek(SeekFrom::Start(0));
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
+
+error: used `seek` to go to the start of the stream
+  --> $DIR/seek_to_start_instead_of_rewind.rs:131:7
+   |
+LL |     f.seek(SeekFrom::Start(0));
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/single_component_path_imports.stderr b/tests/ui/single_component_path_imports.stderr
index 509c88ac256..71dcc25d6e5 100644
--- a/tests/ui/single_component_path_imports.stderr
+++ b/tests/ui/single_component_path_imports.stderr
@@ -1,16 +1,16 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:23:5
+  --> $DIR/single_component_path_imports.rs:5:1
    |
-LL |     use regex;
-   |     ^^^^^^^^^^ help: remove it entirely
+LL | use regex;
+   | ^^^^^^^^^^ help: remove it entirely
    |
    = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:5:1
+  --> $DIR/single_component_path_imports.rs:23:5
    |
-LL | use regex;
-   | ^^^^^^^^^^ help: remove it entirely
+LL |     use regex;
+   |     ^^^^^^^^^^ help: remove it entirely
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/single_component_path_imports_nested_first.stderr b/tests/ui/single_component_path_imports_nested_first.stderr
index 633546f6419..330f285202d 100644
--- a/tests/ui/single_component_path_imports_nested_first.stderr
+++ b/tests/ui/single_component_path_imports_nested_first.stderr
@@ -1,11 +1,18 @@
 error: this import is redundant
+  --> $DIR/single_component_path_imports_nested_first.rs:4:1
+   |
+LL | use regex;
+   | ^^^^^^^^^^ help: remove it entirely
+   |
+   = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
+
+error: this import is redundant
   --> $DIR/single_component_path_imports_nested_first.rs:13:10
    |
 LL |     use {regex, serde};
    |          ^^^^^
    |
    = help: remove this import
-   = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
 
 error: this import is redundant
   --> $DIR/single_component_path_imports_nested_first.rs:13:17
@@ -15,11 +22,5 @@ LL |     use {regex, serde};
    |
    = help: remove this import
 
-error: this import is redundant
-  --> $DIR/single_component_path_imports_nested_first.rs:4:1
-   |
-LL | use regex;
-   | ^^^^^^^^^^ help: remove it entirely
-
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/string_extend.fixed b/tests/ui/string_extend.fixed
index 1883a9f8325..d200d7310fc 100644
--- a/tests/ui/string_extend.fixed
+++ b/tests/ui/string_extend.fixed
@@ -29,4 +29,7 @@ fn main() {
 
     let f = HasChars;
     s.extend(f.chars());
+
+    // issue #9735
+    s.push_str(&abc[0..2]);
 }
diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs
index 07d0baa1be6..0dd96a3b210 100644
--- a/tests/ui/string_extend.rs
+++ b/tests/ui/string_extend.rs
@@ -29,4 +29,7 @@ fn main() {
 
     let f = HasChars;
     s.extend(f.chars());
+
+    // issue #9735
+    s.extend(abc[0..2].chars());
 }
diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr
index 6af8c9e1662..b35c77fd961 100644
--- a/tests/ui/string_extend.stderr
+++ b/tests/ui/string_extend.stderr
@@ -18,5 +18,11 @@ error: calling `.extend(_.chars())`
 LL |     s.extend(def.chars());
    |     ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)`
 
-error: aborting due to 3 previous errors
+error: calling `.extend(_.chars())`
+  --> $DIR/string_extend.rs:34:5
+   |
+LL |     s.extend(abc[0..2].chars());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&abc[0..2])`
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/suspicious_xor_used_as_pow.rs b/tests/ui/suspicious_xor_used_as_pow.rs
new file mode 100644
index 00000000000..eb9fc63fb1d
--- /dev/null
+++ b/tests/ui/suspicious_xor_used_as_pow.rs
@@ -0,0 +1,34 @@
+#![allow(unused)]
+#![warn(clippy::suspicious_xor_used_as_pow)]
+#![allow(clippy::eq_op)]
+
+macro_rules! macro_test {
+    () => {
+        13
+    };
+}
+
+macro_rules! macro_test_inside {
+    () => {
+        1 ^ 2 // should warn even if inside macro
+    };
+}
+
+fn main() {
+    // Should warn:
+    let _ = 2 ^ 5;
+    let _ = 2i32 ^ 9i32;
+    let _ = 2i32 ^ 2i32;
+    let _ = 50i32 ^ 3i32;
+    let _ = 5i32 ^ 8i32;
+    let _ = 2i32 ^ 32i32;
+    macro_test_inside!();
+
+    // Should not warn:
+    let x = 0x02;
+    let _ = x ^ 2;
+    let _ = 2 ^ x;
+    let _ = x ^ 5;
+    let _ = 10 ^ 0b0101;
+    let _ = 2i32 ^ macro_test!();
+}
diff --git a/tests/ui/suspicious_xor_used_as_pow.stderr b/tests/ui/suspicious_xor_used_as_pow.stderr
new file mode 100644
index 00000000000..8bb3c8fbeeb
--- /dev/null
+++ b/tests/ui/suspicious_xor_used_as_pow.stderr
@@ -0,0 +1,51 @@
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:19:13
+   |
+LL |     let _ = 2 ^ 5;
+   |             ^^^^^ help: did you mean to write: `2.pow(5)`
+   |
+   = note: `-D clippy::suspicious-xor-used-as-pow` implied by `-D warnings`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:20:13
+   |
+LL |     let _ = 2i32 ^ 9i32;
+   |             ^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(9_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:21:13
+   |
+LL |     let _ = 2i32 ^ 2i32;
+   |             ^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(2_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:22:13
+   |
+LL |     let _ = 50i32 ^ 3i32;
+   |             ^^^^^^^^^^^^ help: did you mean to write: `50_i32.pow(3_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:23:13
+   |
+LL |     let _ = 5i32 ^ 8i32;
+   |             ^^^^^^^^^^^ help: did you mean to write: `5_i32.pow(8_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:24:13
+   |
+LL |     let _ = 2i32 ^ 32i32;
+   |             ^^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(32_i32)`
+
+error: `^` is not the exponentiation operator
+  --> $DIR/suspicious_xor_used_as_pow.rs:13:9
+   |
+LL |         1 ^ 2 // should warn even if inside macro
+   |         ^^^^^ help: did you mean to write: `1.pow(2)`
+...
+LL |     macro_test_inside!();
+   |     -------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `macro_test_inside` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/swap.fixed b/tests/ui/swap.fixed
index 24b229235d3..805a2ba5a59 100644
--- a/tests/ui/swap.fixed
+++ b/tests/ui/swap.fixed
@@ -155,3 +155,12 @@ fn issue_8154() {
     let s = S3(&mut s);
     std::mem::swap(&mut s.0.x, &mut s.0.y);
 }
+
+const fn issue_9864(mut u: u32) -> u32 {
+    let mut v = 10;
+
+    let temp = u;
+    u = v;
+    v = temp;
+    u + v
+}
diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs
index a318c27919c..a8c87847952 100644
--- a/tests/ui/swap.rs
+++ b/tests/ui/swap.rs
@@ -179,3 +179,12 @@ fn issue_8154() {
     s.0.x = s.0.y;
     s.0.y = t;
 }
+
+const fn issue_9864(mut u: u32) -> u32 {
+    let mut v = 10;
+
+    let temp = u;
+    u = v;
+    v = temp;
+    u + v
+}
diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs
index 001c910239a..1cbacf0feab 100644
--- a/tests/ui/transmute.rs
+++ b/tests/ui/transmute.rs
@@ -1,4 +1,4 @@
-#![allow(dead_code, clippy::borrow_as_ptr)]
+#![allow(dead_code, clippy::borrow_as_ptr, clippy::needless_lifetimes)]
 
 extern crate core;
 
diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs
index af4f3b18443..c0af011d33d 100644
--- a/tests/ui/trivially_copy_pass_by_ref.rs
+++ b/tests/ui/trivially_copy_pass_by_ref.rs
@@ -3,6 +3,7 @@
 #![deny(clippy::trivially_copy_pass_by_ref)]
 #![allow(
     clippy::disallowed_names,
+    clippy::needless_lifetimes,
     clippy::redundant_field_names,
     clippy::uninlined_format_args
 )]
diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr
index 6a8eca96553..8c5cfa8a0f1 100644
--- a/tests/ui/trivially_copy_pass_by_ref.stderr
+++ b/tests/ui/trivially_copy_pass_by_ref.stderr
@@ -1,5 +1,5 @@
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:50:11
+  --> $DIR/trivially_copy_pass_by_ref.rs:51:11
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |           ^^^^ help: consider passing by value instead: `u32`
@@ -11,103 +11,103 @@ LL | #![deny(clippy::trivially_copy_pass_by_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:50:20
+  --> $DIR/trivially_copy_pass_by_ref.rs:51:20
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |                    ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:50:29
+  --> $DIR/trivially_copy_pass_by_ref.rs:51:29
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |                             ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:57:12
+  --> $DIR/trivially_copy_pass_by_ref.rs:58:12
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |            ^^^^^ help: consider passing by value instead: `self`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:57:22
+  --> $DIR/trivially_copy_pass_by_ref.rs:58:22
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                      ^^^^ help: consider passing by value instead: `u32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:57:31
+  --> $DIR/trivially_copy_pass_by_ref.rs:58:31
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                               ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:57:40
+  --> $DIR/trivially_copy_pass_by_ref.rs:58:40
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                                        ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:59:16
+  --> $DIR/trivially_copy_pass_by_ref.rs:60:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:59:25
+  --> $DIR/trivially_copy_pass_by_ref.rs:60:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:59:34
+  --> $DIR/trivially_copy_pass_by_ref.rs:60:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:61:35
+  --> $DIR/trivially_copy_pass_by_ref.rs:62:35
    |
 LL |     fn bad_issue7518(self, other: &Self) {}
    |                                   ^^^^^ help: consider passing by value instead: `Self`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:73:16
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:73:25
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:73:34
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:77:34
+  --> $DIR/trivially_copy_pass_by_ref.rs:78:34
    |
 LL |     fn trait_method(&self, _foo: &Foo);
    |                                  ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:109:21
+  --> $DIR/trivially_copy_pass_by_ref.rs:110:21
    |
 LL |     fn foo_never(x: &i32) {
    |                     ^^^^ help: consider passing by value instead: `i32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:114:15
+  --> $DIR/trivially_copy_pass_by_ref.rs:115:15
    |
 LL |     fn foo(x: &i32) {
    |               ^^^^ help: consider passing by value instead: `i32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:141:37
+  --> $DIR/trivially_copy_pass_by_ref.rs:142:37
    |
 LL | fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
    |                                     ^^^^^^^ help: consider passing by value instead: `u32`
diff --git a/tests/ui/unchecked_duration_subtraction.fixed b/tests/ui/unchecked_duration_subtraction.fixed
new file mode 100644
index 00000000000..a0e49a8beb1
--- /dev/null
+++ b/tests/ui/unchecked_duration_subtraction.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+#![warn(clippy::unchecked_duration_subtraction)]
+
+use std::time::{Duration, Instant};
+
+fn main() {
+    let _first = Instant::now();
+    let second = Duration::from_secs(3);
+
+    let _ = _first.checked_sub(second).unwrap();
+
+    let _ = Instant::now().checked_sub(Duration::from_secs(5)).unwrap();
+
+    let _ = _first.checked_sub(Duration::from_secs(5)).unwrap();
+
+    let _ = Instant::now().checked_sub(second).unwrap();
+}
diff --git a/tests/ui/unchecked_duration_subtraction.rs b/tests/ui/unchecked_duration_subtraction.rs
new file mode 100644
index 00000000000..a14a7ea57cc
--- /dev/null
+++ b/tests/ui/unchecked_duration_subtraction.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+#![warn(clippy::unchecked_duration_subtraction)]
+
+use std::time::{Duration, Instant};
+
+fn main() {
+    let _first = Instant::now();
+    let second = Duration::from_secs(3);
+
+    let _ = _first - second;
+
+    let _ = Instant::now() - Duration::from_secs(5);
+
+    let _ = _first - Duration::from_secs(5);
+
+    let _ = Instant::now() - second;
+}
diff --git a/tests/ui/unchecked_duration_subtraction.stderr b/tests/ui/unchecked_duration_subtraction.stderr
new file mode 100644
index 00000000000..a2e0aa1d7c0
--- /dev/null
+++ b/tests/ui/unchecked_duration_subtraction.stderr
@@ -0,0 +1,28 @@
+error: unchecked subtraction of a 'Duration' from an 'Instant'
+  --> $DIR/unchecked_duration_subtraction.rs:10:13
+   |
+LL |     let _ = _first - second;
+   |             ^^^^^^^^^^^^^^^ help: try: `_first.checked_sub(second).unwrap()`
+   |
+   = note: `-D clippy::unchecked-duration-subtraction` implied by `-D warnings`
+
+error: unchecked subtraction of a 'Duration' from an 'Instant'
+  --> $DIR/unchecked_duration_subtraction.rs:12:13
+   |
+LL |     let _ = Instant::now() - Duration::from_secs(5);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Instant::now().checked_sub(Duration::from_secs(5)).unwrap()`
+
+error: unchecked subtraction of a 'Duration' from an 'Instant'
+  --> $DIR/unchecked_duration_subtraction.rs:14:13
+   |
+LL |     let _ = _first - Duration::from_secs(5);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `_first.checked_sub(Duration::from_secs(5)).unwrap()`
+
+error: unchecked subtraction of a 'Duration' from an 'Instant'
+  --> $DIR/unchecked_duration_subtraction.rs:16:13
+   |
+LL |     let _ = Instant::now() - second;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Instant::now().checked_sub(second).unwrap()`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs
index 08aee433215..cbc6768033e 100644
--- a/tests/ui/undocumented_unsafe_blocks.rs
+++ b/tests/ui/undocumented_unsafe_blocks.rs
@@ -490,4 +490,23 @@ unsafe impl CrateRoot for () {}
 // SAFETY: ok
 unsafe impl CrateRoot for (i32) {}
 
+fn issue_9142() {
+    // SAFETY: ok
+    let _ =
+        // we need this comment to avoid rustfmt putting
+        // it all on one line
+        unsafe {};
+
+    // SAFETY: this is more than one level away, so it should warn
+    let _ = {
+        if unsafe { true } {
+            todo!();
+        } else {
+            let bar = unsafe {};
+            todo!();
+            bar
+        }
+    };
+}
+
 fn main() {}
diff --git a/tests/ui/undocumented_unsafe_blocks.stderr b/tests/ui/undocumented_unsafe_blocks.stderr
index 2c466ff5c73..ba4de9806d1 100644
--- a/tests/ui/undocumented_unsafe_blocks.stderr
+++ b/tests/ui/undocumented_unsafe_blocks.stderr
@@ -263,5 +263,29 @@ LL | unsafe impl CrateRoot for () {}
    |
    = help: consider adding a safety comment on the preceding line
 
-error: aborting due to 31 previous errors
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:498:9
+   |
+LL |         unsafe {};
+   |         ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:502:12
+   |
+LL |         if unsafe { true } {
+   |            ^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:505:23
+   |
+LL |             let bar = unsafe {};
+   |                       ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: aborting due to 34 previous errors
 
diff --git a/tests/ui/unnecessary_join.stderr b/tests/ui/unnecessary_join.stderr
index 0b14b143aff..e919a6d1d8a 100644
--- a/tests/ui/unnecessary_join.stderr
+++ b/tests/ui/unnecessary_join.stderr
@@ -1,4 +1,4 @@
-error: called `.collect<Vec<String>>().join("")` on an iterator
+error: called `.collect::<Vec<String>>().join("")` on an iterator
   --> $DIR/unnecessary_join.rs:11:10
    |
 LL |           .collect::<Vec<String>>()
@@ -8,7 +8,7 @@ LL | |         .join("");
    |
    = note: `-D clippy::unnecessary-join` implied by `-D warnings`
 
-error: called `.collect<Vec<String>>().join("")` on an iterator
+error: called `.collect::<Vec<String>>().join("")` on an iterator
   --> $DIR/unnecessary_join.rs:20:10
    |
 LL |           .collect::<Vec<_>>()
diff --git a/tests/ui/unused_rounding.fixed b/tests/ui/unused_rounding.fixed
index 54f85806ac3..38fe6c34cfe 100644
--- a/tests/ui/unused_rounding.fixed
+++ b/tests/ui/unused_rounding.fixed
@@ -6,4 +6,9 @@ fn main() {
     let _ = 1.0f64;
     let _ = 1.00f32;
     let _ = 2e-54f64.floor();
+
+    // issue9866
+    let _ = 3.3_f32.round();
+    let _ = 3.3_f64.round();
+    let _ = 3.0_f32;
 }
diff --git a/tests/ui/unused_rounding.rs b/tests/ui/unused_rounding.rs
index 8d007bc4a1d..a5cac64d023 100644
--- a/tests/ui/unused_rounding.rs
+++ b/tests/ui/unused_rounding.rs
@@ -6,4 +6,9 @@ fn main() {
     let _ = 1.0f64.floor();
     let _ = 1.00f32.round();
     let _ = 2e-54f64.floor();
+
+    // issue9866
+    let _ = 3.3_f32.round();
+    let _ = 3.3_f64.round();
+    let _ = 3.0_f32.round();
 }
diff --git a/tests/ui/unused_rounding.stderr b/tests/ui/unused_rounding.stderr
index 6cfb02e0402..1eeb5d1de88 100644
--- a/tests/ui/unused_rounding.stderr
+++ b/tests/ui/unused_rounding.stderr
@@ -18,5 +18,11 @@ error: used the `round` method with a whole number float
 LL |     let _ = 1.00f32.round();
    |             ^^^^^^^^^^^^^^^ help: remove the `round` method call: `1.00f32`
 
-error: aborting due to 3 previous errors
+error: used the `round` method with a whole number float
+  --> $DIR/unused_rounding.rs:13:13
+   |
+LL |     let _ = 3.0_f32.round();
+   |             ^^^^^^^^^^^^^^^ help: remove the `round` method call: `3.0_f32`
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/unused_unit.fixed b/tests/ui/unused_unit.fixed
index 7bb43cf7ae8..3dd640b86f0 100644
--- a/tests/ui/unused_unit.fixed
+++ b/tests/ui/unused_unit.fixed
@@ -7,6 +7,7 @@
 // test of the JSON error format.
 
 #![feature(custom_inner_attributes)]
+#![feature(closure_lifetime_binder)]
 #![rustfmt::skip]
 
 #![deny(clippy::unused_unit)]
@@ -87,3 +88,9 @@ fn macro_expr() {
     }
     e!()
 }
+
+mod issue9748 {
+    fn main() {
+        let _ = for<'a> |_: &'a u32| -> () {};
+    }
+}
diff --git a/tests/ui/unused_unit.rs b/tests/ui/unused_unit.rs
index 21073fb802a..bddecf06fb7 100644
--- a/tests/ui/unused_unit.rs
+++ b/tests/ui/unused_unit.rs
@@ -7,6 +7,7 @@
 // test of the JSON error format.
 
 #![feature(custom_inner_attributes)]
+#![feature(closure_lifetime_binder)]
 #![rustfmt::skip]
 
 #![deny(clippy::unused_unit)]
@@ -87,3 +88,9 @@ fn macro_expr() {
     }
     e!()
 }
+
+mod issue9748 {
+    fn main() {
+        let _ = for<'a> |_: &'a u32| -> () {};
+    }
+}
diff --git a/tests/ui/unused_unit.stderr b/tests/ui/unused_unit.stderr
index 0d2cb77855b..ce06738cfe4 100644
--- a/tests/ui/unused_unit.stderr
+++ b/tests/ui/unused_unit.stderr
@@ -1,119 +1,119 @@
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:19:58
+  --> $DIR/unused_unit.rs:20:58
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
    |                                                          ^^^^^^ help: remove the `-> ()`
    |
 note: the lint level is defined here
-  --> $DIR/unused_unit.rs:12:9
+  --> $DIR/unused_unit.rs:13:9
    |
 LL | #![deny(clippy::unused_unit)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:19:28
+  --> $DIR/unused_unit.rs:20:28
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
    |                            ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:20:18
+  --> $DIR/unused_unit.rs:21:18
    |
 LL |     where G: Fn() -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:21:26
+  --> $DIR/unused_unit.rs:22:26
    |
 LL |         let _y: &dyn Fn() -> () = &f;
    |                          ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:28:18
+  --> $DIR/unused_unit.rs:29:18
    |
 LL |     fn into(self) -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit expression
-  --> $DIR/unused_unit.rs:29:9
+  --> $DIR/unused_unit.rs:30:9
    |
 LL |         ()
    |         ^^ help: remove the final `()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:34:29
+  --> $DIR/unused_unit.rs:35:29
    |
 LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
    |                             ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:36:19
+  --> $DIR/unused_unit.rs:37:19
    |
 LL |         G: FnMut() -> (),
    |                   ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:37:16
+  --> $DIR/unused_unit.rs:38:16
    |
 LL |         H: Fn() -> ();
    |                ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:41:29
+  --> $DIR/unused_unit.rs:42:29
    |
 LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
    |                             ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:43:19
+  --> $DIR/unused_unit.rs:44:19
    |
 LL |         G: FnMut() -> (),
    |                   ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:44:16
+  --> $DIR/unused_unit.rs:45:16
    |
 LL |         H: Fn() -> () {}
    |                ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:47:17
+  --> $DIR/unused_unit.rs:48:17
    |
 LL | fn return_unit() -> () { () }
    |                 ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit expression
-  --> $DIR/unused_unit.rs:47:26
+  --> $DIR/unused_unit.rs:48:26
    |
 LL | fn return_unit() -> () { () }
    |                          ^^ help: remove the final `()`
 
 error: unneeded `()`
-  --> $DIR/unused_unit.rs:57:14
+  --> $DIR/unused_unit.rs:58:14
    |
 LL |         break();
    |              ^^ help: remove the `()`
 
 error: unneeded `()`
-  --> $DIR/unused_unit.rs:59:11
+  --> $DIR/unused_unit.rs:60:11
    |
 LL |     return();
    |           ^^ help: remove the `()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:76:10
+  --> $DIR/unused_unit.rs:77:10
    |
 LL | fn test()->(){}
    |          ^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:79:11
+  --> $DIR/unused_unit.rs:80:11
    |
 LL | fn test2() ->(){}
    |           ^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:82:11
+  --> $DIR/unused_unit.rs:83:11
    |
 LL | fn test3()-> (){}
    |           ^^^^^ help: remove the `-> ()`
diff --git a/tests/ui/unwrap.stderr b/tests/ui/unwrap.stderr
index e88d580f7bd..d49bf2b3228 100644
--- a/tests/ui/unwrap.stderr
+++ b/tests/ui/unwrap.stderr
@@ -1,4 +1,4 @@
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap.rs:5:13
    |
 LL |     let _ = opt.unwrap();
@@ -7,7 +7,7 @@ LL |     let _ = opt.unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
-error: used `unwrap()` on `a Result` value
+error: used `unwrap()` on a `Result` value
   --> $DIR/unwrap.rs:10:13
    |
 LL |     let _ = res.unwrap();
@@ -15,7 +15,7 @@ LL |     let _ = res.unwrap();
    |
    = help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message
 
-error: used `unwrap_err()` on `a Result` value
+error: used `unwrap_err()` on a `Result` value
   --> $DIR/unwrap.rs:11:13
    |
 LL |     let _ = res.unwrap_err();
diff --git a/tests/ui/unwrap_expect_used.stderr b/tests/ui/unwrap_expect_used.stderr
index 211d2be1834..fe4ecef1145 100644
--- a/tests/ui/unwrap_expect_used.stderr
+++ b/tests/ui/unwrap_expect_used.stderr
@@ -1,4 +1,4 @@
-error: used `unwrap()` on `an Option` value
+error: used `unwrap()` on an `Option` value
   --> $DIR/unwrap_expect_used.rs:23:5
    |
 LL |     Some(3).unwrap();
@@ -7,7 +7,7 @@ LL |     Some(3).unwrap();
    = help: if this value is `None`, it will panic
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
-error: used `expect()` on `an Option` value
+error: used `expect()` on an `Option` value
   --> $DIR/unwrap_expect_used.rs:24:5
    |
 LL |     Some(3).expect("Hello world!");
@@ -16,7 +16,7 @@ LL |     Some(3).expect("Hello world!");
    = help: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
-error: used `unwrap()` on `a Result` value
+error: used `unwrap()` on a `Result` value
   --> $DIR/unwrap_expect_used.rs:31:5
    |
 LL |     a.unwrap();
@@ -24,7 +24,7 @@ LL |     a.unwrap();
    |
    = help: if this value is an `Err`, it will panic
 
-error: used `expect()` on `a Result` value
+error: used `expect()` on a `Result` value
   --> $DIR/unwrap_expect_used.rs:32:5
    |
 LL |     a.expect("Hello world!");
@@ -32,7 +32,7 @@ LL |     a.expect("Hello world!");
    |
    = help: if this value is an `Err`, it will panic
 
-error: used `unwrap_err()` on `a Result` value
+error: used `unwrap_err()` on a `Result` value
   --> $DIR/unwrap_expect_used.rs:33:5
    |
 LL |     a.unwrap_err();
@@ -40,7 +40,7 @@ LL |     a.unwrap_err();
    |
    = help: if this value is an `Ok`, it will panic
 
-error: used `expect_err()` on `a Result` value
+error: used `expect_err()` on a `Result` value
   --> $DIR/unwrap_expect_used.rs:34:5
    |
 LL |     a.expect_err("Hello error!");
diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs
index bfb41e43947..a0c003f5b1e 100644
--- a/tests/ui/unwrap_or.rs
+++ b/tests/ui/unwrap_or.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::all)]
+#![warn(clippy::all, clippy::or_fun_call)]
 
 fn main() {
     let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len();
diff --git a/tests/ui/use_self_trait.fixed b/tests/ui/use_self_trait.fixed
index 9bcd692fb35..4e779308d02 100644
--- a/tests/ui/use_self_trait.fixed
+++ b/tests/ui/use_self_trait.fixed
@@ -47,8 +47,7 @@ impl Mul for Bad {
 
 impl Clone for Bad {
     fn clone(&self) -> Self {
-        // FIXME: applicable here
-        Bad
+        Self
     }
 }
 
@@ -112,4 +111,42 @@ impl NameTrait for u8 {
     }
 }
 
+mod impl_in_macro {
+    macro_rules! parse_ip_impl {
+        // minimized from serde=1.0.118
+        ($ty:ty) => {
+            impl FooTrait for $ty {
+                fn new() -> Self {
+                    <$ty>::bar()
+                }
+            }
+        };
+    }
+
+    struct Foo;
+
+    trait FooTrait {
+        fn new() -> Self;
+    }
+
+    impl Foo {
+        fn bar() -> Self {
+            Self
+        }
+    }
+    parse_ip_impl!(Foo); // Should not lint
+}
+
+mod full_path_replacement {
+    trait Error {
+        fn custom<T: std::fmt::Display>(_msg: T) -> Self;
+    }
+
+    impl Error for std::fmt::Error {
+        fn custom<T: std::fmt::Display>(_msg: T) -> Self {
+            Self // Should lint
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/use_self_trait.rs b/tests/ui/use_self_trait.rs
index de305d40f33..325dc73b21e 100644
--- a/tests/ui/use_self_trait.rs
+++ b/tests/ui/use_self_trait.rs
@@ -47,7 +47,6 @@ impl Mul for Bad {
 
 impl Clone for Bad {
     fn clone(&self) -> Self {
-        // FIXME: applicable here
         Bad
     }
 }
@@ -112,4 +111,42 @@ impl NameTrait for u8 {
     }
 }
 
+mod impl_in_macro {
+    macro_rules! parse_ip_impl {
+        // minimized from serde=1.0.118
+        ($ty:ty) => {
+            impl FooTrait for $ty {
+                fn new() -> Self {
+                    <$ty>::bar()
+                }
+            }
+        };
+    }
+
+    struct Foo;
+
+    trait FooTrait {
+        fn new() -> Self;
+    }
+
+    impl Foo {
+        fn bar() -> Self {
+            Self
+        }
+    }
+    parse_ip_impl!(Foo); // Should not lint
+}
+
+mod full_path_replacement {
+    trait Error {
+        fn custom<T: std::fmt::Display>(_msg: T) -> Self;
+    }
+
+    impl Error for std::fmt::Error {
+        fn custom<T: std::fmt::Display>(_msg: T) -> Self {
+            std::fmt::Error // Should lint
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/use_self_trait.stderr b/tests/ui/use_self_trait.stderr
index 55af3ff2a93..090729b9c3d 100644
--- a/tests/ui/use_self_trait.stderr
+++ b/tests/ui/use_self_trait.stderr
@@ -84,5 +84,17 @@ error: unnecessary structure name repetition
 LL |     fn mul(self, rhs: Bad) -> Bad {
    |                               ^^^ help: use the applicable keyword: `Self`
 
-error: aborting due to 14 previous errors
+error: unnecessary structure name repetition
+  --> $DIR/use_self_trait.rs:50:9
+   |
+LL |         Bad
+   |         ^^^ help: use the applicable keyword: `Self`
+
+error: unnecessary structure name repetition
+  --> $DIR/use_self_trait.rs:147:13
+   |
+LL |             std::fmt::Error // Should lint
+   |             ^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
+
+error: aborting due to 16 previous errors
 
diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed
index c23231a99e9..871e4fb5c3a 100644
--- a/tests/ui/useless_attribute.fixed
+++ b/tests/ui/useless_attribute.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 // aux-build:proc_macro_derive.rs
 
+#![allow(unused)]
 #![warn(clippy::useless_attribute)]
 #![warn(unreachable_pub)]
 #![feature(rustc_private)]
@@ -16,6 +17,13 @@ extern crate rustc_middle;
 #[macro_use]
 extern crate proc_macro_derive;
 
+fn test_indented_attr() {
+    #![allow(clippy::almost_swapped)]
+    use std::collections::HashSet;
+
+    let _ = HashSet::<u32>::default();
+}
+
 // don't lint on unused_import for `use` items
 #[allow(unused_imports)]
 use std::collections;
@@ -63,13 +71,16 @@ mod c {
     pub(crate) struct S;
 }
 
-fn test_indented_attr() {
-    #![allow(clippy::almost_swapped)]
-    use std::collections::HashSet;
-
-    let _ = HashSet::<u32>::default();
+// https://github.com/rust-lang/rust-clippy/issues/7511
+pub mod split {
+    #[allow(clippy::module_name_repetitions)]
+    pub use regex::SplitN;
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/8768
+#[allow(clippy::single_component_path_imports)]
+use regex;
+
 fn main() {
     test_indented_attr();
 }
diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs
index 7a7b198ea60..cb50736ba39 100644
--- a/tests/ui/useless_attribute.rs
+++ b/tests/ui/useless_attribute.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 // aux-build:proc_macro_derive.rs
 
+#![allow(unused)]
 #![warn(clippy::useless_attribute)]
 #![warn(unreachable_pub)]
 #![feature(rustc_private)]
@@ -16,6 +17,13 @@ extern crate rustc_middle;
 #[macro_use]
 extern crate proc_macro_derive;
 
+fn test_indented_attr() {
+    #[allow(clippy::almost_swapped)]
+    use std::collections::HashSet;
+
+    let _ = HashSet::<u32>::default();
+}
+
 // don't lint on unused_import for `use` items
 #[allow(unused_imports)]
 use std::collections;
@@ -63,13 +71,16 @@ mod c {
     pub(crate) struct S;
 }
 
-fn test_indented_attr() {
-    #[allow(clippy::almost_swapped)]
-    use std::collections::HashSet;
-
-    let _ = HashSet::<u32>::default();
+// https://github.com/rust-lang/rust-clippy/issues/7511
+pub mod split {
+    #[allow(clippy::module_name_repetitions)]
+    pub use regex::SplitN;
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/8768
+#[allow(clippy::single_component_path_imports)]
+use regex;
+
 fn main() {
     test_indented_attr();
 }
diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr
index 255d2876355..a7ea0df2294 100644
--- a/tests/ui/useless_attribute.stderr
+++ b/tests/ui/useless_attribute.stderr
@@ -1,5 +1,5 @@
 error: useless lint attribute
-  --> $DIR/useless_attribute.rs:8:1
+  --> $DIR/useless_attribute.rs:9:1
    |
 LL | #[allow(dead_code)]
    | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]`
@@ -7,13 +7,13 @@ LL | #[allow(dead_code)]
    = note: `-D clippy::useless-attribute` implied by `-D warnings`
 
 error: useless lint attribute
-  --> $DIR/useless_attribute.rs:9:1
+  --> $DIR/useless_attribute.rs:10:1
    |
 LL | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)`
 
 error: useless lint attribute
-  --> $DIR/useless_attribute.rs:67:5
+  --> $DIR/useless_attribute.rs:21:5
    |
 LL |     #[allow(clippy::almost_swapped)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(clippy::almost_swapped)]`
diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs
index a6d8d0307ce..7a85386a3df 100644
--- a/tests/versioncheck.rs
+++ b/tests/versioncheck.rs
@@ -6,7 +6,7 @@ use rustc_tools_util::VersionInfo;
 use std::fs;
 
 #[test]
-fn check_that_clippy_lints_and_clippy_utils_have_the_same_version_as_clippy() {
+fn consistent_clippy_crate_versions() {
     fn read_version(path: &str) -> String {
         let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("error reading `{path}`: {e:?}"));
         contents
@@ -24,11 +24,16 @@ fn check_that_clippy_lints_and_clippy_utils_have_the_same_version_as_clippy() {
     }
 
     let clippy_version = read_version("Cargo.toml");
-    let clippy_lints_version = read_version("clippy_lints/Cargo.toml");
-    let clippy_utils_version = read_version("clippy_utils/Cargo.toml");
 
-    assert_eq!(clippy_version, clippy_lints_version);
-    assert_eq!(clippy_version, clippy_utils_version);
+    let paths = [
+        "declare_clippy_lint/Cargo.toml",
+        "clippy_lints/Cargo.toml",
+        "clippy_utils/Cargo.toml",
+    ];
+
+    for path in paths {
+        assert_eq!(clippy_version, read_version(path), "{path} version differs");
+    }
 }
 
 #[test]