about summary refs log tree commit diff
path: root/tests/ui
diff options
context:
space:
mode:
authorflip1995 <philipp.krones@embecosm.com>2021-09-08 10:50:04 +0200
committerflip1995 <philipp.krones@embecosm.com>2021-09-08 10:51:27 +0200
commit4962608ca6929874894e683ab38dbf5fe63df35d (patch)
tree4dd56db81ec0bcb37a599edca20dbcc2ce3db427 /tests/ui
parentf7aaa2a200d2e7809969ca2d8179e36fa7d90c2b (diff)
parentb7c25e1679e8741ec52294765bb943c298ecefd7 (diff)
downloadrust-4962608ca6929874894e683ab38dbf5fe63df35d.tar.gz
rust-4962608ca6929874894e683ab38dbf5fe63df35d.zip
Merge remote-tracking branch 'upstream/master' into rustup
Diffstat (limited to 'tests/ui')
-rw-r--r--tests/ui/approx_const.rs4
-rw-r--r--tests/ui/approx_const.stderr101
-rw-r--r--tests/ui/auxiliary/option_helpers.rs9
-rw-r--r--tests/ui/bool_assert_comparison.rs63
-rw-r--r--tests/ui/bool_assert_comparison.stderr62
-rw-r--r--tests/ui/box_vec.rs28
-rw-r--r--tests/ui/box_vec.stderr6
-rw-r--r--tests/ui/checked_unwrap/complex_conditionals.stderr39
-rw-r--r--tests/ui/checked_unwrap/complex_conditionals_nested.stderr4
-rw-r--r--tests/ui/checked_unwrap/simple_conditionals.rs4
-rw-r--r--tests/ui/checked_unwrap/simple_conditionals.stderr90
-rw-r--r--tests/ui/derivable_impls.rs170
-rw-r--r--tests/ui/derivable_impls.stderr77
-rw-r--r--tests/ui/entry.fixed15
-rw-r--r--tests/ui/entry.rs9
-rw-r--r--tests/ui/entry.stderr16
-rw-r--r--tests/ui/entry_btree.fixed18
-rw-r--r--tests/ui/entry_btree.rs18
-rw-r--r--tests/ui/entry_btree.stderr20
-rw-r--r--tests/ui/linkedlist.rs31
-rw-r--r--tests/ui/linkedlist.stderr24
-rw-r--r--tests/ui/manual_flatten.rs13
-rw-r--r--tests/ui/manual_map_option_2.fixed50
-rw-r--r--tests/ui/manual_map_option_2.rs56
-rw-r--r--tests/ui/manual_map_option_2.stderr43
-rw-r--r--tests/ui/manual_split_once.fixed50
-rw-r--r--tests/ui/manual_split_once.rs50
-rw-r--r--tests/ui/manual_split_once.stderr82
-rw-r--r--tests/ui/mem_replace.fixed20
-rw-r--r--tests/ui/mem_replace.rs20
-rw-r--r--tests/ui/mem_replace.stderr20
-rw-r--r--tests/ui/methods.rs5
-rw-r--r--tests/ui/min_rust_version_attr.rs5
-rw-r--r--tests/ui/min_rust_version_attr.stderr8
-rw-r--r--tests/ui/missing-doc-crate.stderr0
-rw-r--r--tests/ui/missing_const_for_fn/cant_be_const.stderr0
-rw-r--r--tests/ui/needless_option_as_deref.fixed13
-rw-r--r--tests/ui/needless_option_as_deref.rs13
-rw-r--r--tests/ui/needless_option_as_deref.stderr16
-rw-r--r--tests/ui/option_if_let_else.fixed62
-rw-r--r--tests/ui/option_if_let_else.rs68
-rw-r--r--tests/ui/option_if_let_else.stderr72
-rw-r--r--tests/ui/proc_macro.stderr3
-rw-r--r--tests/ui/rc_buffer_redefined_string.stderr0
-rw-r--r--tests/ui/rc_mutex.rs32
-rw-r--r--tests/ui/rc_mutex.stderr33
-rw-r--r--tests/ui/redundant_allocation.rs20
-rw-r--r--tests/ui/redundant_allocation.stderr11
-rw-r--r--tests/ui/temporary_assignment.rs1
-rw-r--r--tests/ui/temporary_assignment.stderr8
-rw-r--r--tests/ui/unnecessary_operation.fixed4
-rw-r--r--tests/ui/unnecessary_operation.stderr80
52 files changed, 1435 insertions, 231 deletions
diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs
index fb57a0becbb..2ae4d613507 100644
--- a/tests/ui/approx_const.rs
+++ b/tests/ui/approx_const.rs
@@ -57,4 +57,8 @@ fn main() {
 
     let my_sq2 = 1.4142;
     let no_sq2 = 1.414;
+
+    let my_tau = 6.2832;
+    let almost_tau = 6.28;
+    let no_tau = 6.3;
 }
diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr
index 98b85443f0b..4da1b8215ae 100644
--- a/tests/ui/approx_const.stderr
+++ b/tests/ui/approx_const.stderr
@@ -1,130 +1,187 @@
-error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::E` found
   --> $DIR/approx_const.rs:4:16
    |
 LL |     let my_e = 2.7182;
    |                ^^^^^^
    |
    = note: `-D clippy::approx-constant` implied by `-D warnings`
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::E` found
   --> $DIR/approx_const.rs:5:20
    |
 LL |     let almost_e = 2.718;
    |                    ^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found
   --> $DIR/approx_const.rs:8:24
    |
 LL |     let my_1_frac_pi = 0.3183;
    |                        ^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
   --> $DIR/approx_const.rs:11:28
    |
 LL |     let my_frac_1_sqrt_2 = 0.70710678;
    |                            ^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
   --> $DIR/approx_const.rs:12:32
    |
 LL |     let almost_frac_1_sqrt_2 = 0.70711;
    |                                ^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found
   --> $DIR/approx_const.rs:15:24
    |
 LL |     let my_frac_2_pi = 0.63661977;
    |                        ^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found
   --> $DIR/approx_const.rs:18:27
    |
 LL |     let my_frac_2_sq_pi = 1.128379;
    |                           ^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found
   --> $DIR/approx_const.rs:21:24
    |
 LL |     let my_frac_pi_2 = 1.57079632679;
    |                        ^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found
   --> $DIR/approx_const.rs:24:24
    |
 LL |     let my_frac_pi_3 = 1.04719755119;
    |                        ^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found
   --> $DIR/approx_const.rs:27:24
    |
 LL |     let my_frac_pi_4 = 0.785398163397;
    |                        ^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found
   --> $DIR/approx_const.rs:30:24
    |
 LL |     let my_frac_pi_6 = 0.523598775598;
    |                        ^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found
   --> $DIR/approx_const.rs:33:24
    |
 LL |     let my_frac_pi_8 = 0.3926990816987;
    |                        ^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LN_10` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LN_10` found
   --> $DIR/approx_const.rs:36:20
    |
 LL |     let my_ln_10 = 2.302585092994046;
    |                    ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LN_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LN_2` found
   --> $DIR/approx_const.rs:39:19
    |
 LL |     let my_ln_2 = 0.6931471805599453;
    |                   ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LOG10_E` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LOG10_E` found
   --> $DIR/approx_const.rs:42:22
    |
 LL |     let my_log10_e = 0.4342944819032518;
    |                      ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LOG2_E` found
   --> $DIR/approx_const.rs:45:21
    |
 LL |     let my_log2_e = 1.4426950408889634;
    |                     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LOG2_10` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LOG2_10` found
   --> $DIR/approx_const.rs:48:19
    |
 LL |     let log2_10 = 3.321928094887362;
    |                   ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LOG10_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LOG10_2` found
   --> $DIR/approx_const.rs:51:19
    |
 LL |     let log10_2 = 0.301029995663981;
    |                   ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::PI` found
   --> $DIR/approx_const.rs:54:17
    |
 LL |     let my_pi = 3.1415;
    |                 ^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::PI` found
   --> $DIR/approx_const.rs:55:21
    |
 LL |     let almost_pi = 3.14;
    |                     ^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::SQRT_2` found
   --> $DIR/approx_const.rs:58:18
    |
 LL |     let my_sq2 = 1.4142;
    |                  ^^^^^^
+   |
+   = help: consider using the constant directly
+
+error: approximate value of `f{32, 64}::consts::TAU` found
+  --> $DIR/approx_const.rs:61:18
+   |
+LL |     let my_tau = 6.2832;
+   |                  ^^^^^^
+   |
+   = help: consider using the constant directly
+
+error: approximate value of `f{32, 64}::consts::TAU` found
+  --> $DIR/approx_const.rs:62:22
+   |
+LL |     let almost_tau = 6.28;
+   |                      ^^^^
+   |
+   = help: consider using the constant directly
 
-error: aborting due to 21 previous errors
+error: aborting due to 23 previous errors
 
diff --git a/tests/ui/auxiliary/option_helpers.rs b/tests/ui/auxiliary/option_helpers.rs
index 7dc3f4ebd4d..86a637ce309 100644
--- a/tests/ui/auxiliary/option_helpers.rs
+++ b/tests/ui/auxiliary/option_helpers.rs
@@ -53,3 +53,12 @@ impl IteratorFalsePositives {
         self.foo as usize
     }
 }
+
+#[derive(Copy, Clone)]
+pub struct IteratorMethodFalsePositives;
+
+impl IteratorMethodFalsePositives {
+    pub fn filter(&self, _s: i32) -> std::vec::IntoIter<i32> {
+        unimplemented!();
+    }
+}
diff --git a/tests/ui/bool_assert_comparison.rs b/tests/ui/bool_assert_comparison.rs
index 2de402fae8c..ec4d6f3ff84 100644
--- a/tests/ui/bool_assert_comparison.rs
+++ b/tests/ui/bool_assert_comparison.rs
@@ -1,5 +1,7 @@
 #![warn(clippy::bool_assert_comparison)]
 
+use std::ops::Not;
+
 macro_rules! a {
     () => {
         true
@@ -11,7 +13,58 @@ macro_rules! b {
     };
 }
 
+// Implements the Not trait but with an output type
+// that's not bool. Should not suggest a rewrite
+#[derive(Debug)]
+enum ImplNotTraitWithoutBool {
+    VariantX(bool),
+    VariantY(u32),
+}
+
+impl PartialEq<bool> for ImplNotTraitWithoutBool {
+    fn eq(&self, other: &bool) -> bool {
+        match *self {
+            ImplNotTraitWithoutBool::VariantX(b) => b == *other,
+            _ => false,
+        }
+    }
+}
+
+impl Not for ImplNotTraitWithoutBool {
+    type Output = Self;
+
+    fn not(self) -> Self::Output {
+        match self {
+            ImplNotTraitWithoutBool::VariantX(b) => ImplNotTraitWithoutBool::VariantX(!b),
+            ImplNotTraitWithoutBool::VariantY(0) => ImplNotTraitWithoutBool::VariantY(1),
+            ImplNotTraitWithoutBool::VariantY(_) => ImplNotTraitWithoutBool::VariantY(0),
+        }
+    }
+}
+
+// This type implements the Not trait with an Output of
+// type bool. Using assert!(..) must be suggested
+#[derive(Debug)]
+struct ImplNotTraitWithBool;
+
+impl PartialEq<bool> for ImplNotTraitWithBool {
+    fn eq(&self, other: &bool) -> bool {
+        false
+    }
+}
+
+impl Not for ImplNotTraitWithBool {
+    type Output = bool;
+
+    fn not(self) -> Self::Output {
+        true
+    }
+}
+
 fn main() {
+    let a = ImplNotTraitWithoutBool::VariantX(true);
+    let b = ImplNotTraitWithBool;
+
     assert_eq!("a".len(), 1);
     assert_eq!("a".is_empty(), false);
     assert_eq!("".is_empty(), true);
@@ -19,6 +72,8 @@ fn main() {
     assert_eq!(a!(), b!());
     assert_eq!(a!(), "".is_empty());
     assert_eq!("".is_empty(), b!());
+    assert_eq!(a, true);
+    assert_eq!(b, true);
 
     assert_ne!("a".len(), 1);
     assert_ne!("a".is_empty(), false);
@@ -27,6 +82,8 @@ fn main() {
     assert_ne!(a!(), b!());
     assert_ne!(a!(), "".is_empty());
     assert_ne!("".is_empty(), b!());
+    assert_ne!(a, true);
+    assert_ne!(b, true);
 
     debug_assert_eq!("a".len(), 1);
     debug_assert_eq!("a".is_empty(), false);
@@ -35,6 +92,8 @@ fn main() {
     debug_assert_eq!(a!(), b!());
     debug_assert_eq!(a!(), "".is_empty());
     debug_assert_eq!("".is_empty(), b!());
+    debug_assert_eq!(a, true);
+    debug_assert_eq!(b, true);
 
     debug_assert_ne!("a".len(), 1);
     debug_assert_ne!("a".is_empty(), false);
@@ -43,6 +102,8 @@ fn main() {
     debug_assert_ne!(a!(), b!());
     debug_assert_ne!(a!(), "".is_empty());
     debug_assert_ne!("".is_empty(), b!());
+    debug_assert_ne!(a, true);
+    debug_assert_ne!(b, true);
 
     // assert with error messages
     assert_eq!("a".len(), 1, "tadam {}", 1);
@@ -50,10 +111,12 @@ fn main() {
     assert_eq!("a".is_empty(), false, "tadam {}", 1);
     assert_eq!("a".is_empty(), false, "tadam {}", true);
     assert_eq!(false, "a".is_empty(), "tadam {}", true);
+    assert_eq!(a, true, "tadam {}", false);
 
     debug_assert_eq!("a".len(), 1, "tadam {}", 1);
     debug_assert_eq!("a".len(), 1, "tadam {}", true);
     debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
     debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
     debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
+    debug_assert_eq!(a, true, "tadam {}", false);
 }
diff --git a/tests/ui/bool_assert_comparison.stderr b/tests/ui/bool_assert_comparison.stderr
index f57acf520d5..da9b56aa779 100644
--- a/tests/ui/bool_assert_comparison.stderr
+++ b/tests/ui/bool_assert_comparison.stderr
@@ -1,5 +1,5 @@
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:16:5
+  --> $DIR/bool_assert_comparison.rs:69:5
    |
 LL |     assert_eq!("a".is_empty(), false);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
@@ -7,106 +7,130 @@ LL |     assert_eq!("a".is_empty(), false);
    = note: `-D clippy::bool-assert-comparison` implied by `-D warnings`
 
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:17:5
+  --> $DIR/bool_assert_comparison.rs:70:5
    |
 LL |     assert_eq!("".is_empty(), true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:18:5
+  --> $DIR/bool_assert_comparison.rs:71:5
    |
 LL |     assert_eq!(true, "".is_empty());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
+error: used `assert_eq!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:76:5
+   |
+LL |     assert_eq!(b, true);
+   |     ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+
 error: used `assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:24:5
+  --> $DIR/bool_assert_comparison.rs:79:5
    |
 LL |     assert_ne!("a".is_empty(), false);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:25:5
+  --> $DIR/bool_assert_comparison.rs:80:5
    |
 LL |     assert_ne!("".is_empty(), true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:26:5
+  --> $DIR/bool_assert_comparison.rs:81:5
    |
 LL |     assert_ne!(true, "".is_empty());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
+error: used `assert_ne!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:86:5
+   |
+LL |     assert_ne!(b, true);
+   |     ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:32:5
+  --> $DIR/bool_assert_comparison.rs:89:5
    |
 LL |     debug_assert_eq!("a".is_empty(), false);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:33:5
+  --> $DIR/bool_assert_comparison.rs:90:5
    |
 LL |     debug_assert_eq!("".is_empty(), true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:34:5
+  --> $DIR/bool_assert_comparison.rs:91:5
    |
 LL |     debug_assert_eq!(true, "".is_empty());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
+error: used `debug_assert_eq!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:96:5
+   |
+LL |     debug_assert_eq!(b, true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+
 error: used `debug_assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:40:5
+  --> $DIR/bool_assert_comparison.rs:99:5
    |
 LL |     debug_assert_ne!("a".is_empty(), false);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:41:5
+  --> $DIR/bool_assert_comparison.rs:100:5
    |
 LL |     debug_assert_ne!("".is_empty(), true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:42:5
+  --> $DIR/bool_assert_comparison.rs:101:5
    |
 LL |     debug_assert_ne!(true, "".is_empty());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
+error: used `debug_assert_ne!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:106:5
+   |
+LL |     debug_assert_ne!(b, true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:50:5
+  --> $DIR/bool_assert_comparison.rs:111:5
    |
 LL |     assert_eq!("a".is_empty(), false, "tadam {}", 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:51:5
+  --> $DIR/bool_assert_comparison.rs:112:5
    |
 LL |     assert_eq!("a".is_empty(), false, "tadam {}", true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:52:5
+  --> $DIR/bool_assert_comparison.rs:113:5
    |
 LL |     assert_eq!(false, "a".is_empty(), "tadam {}", true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:56:5
+  --> $DIR/bool_assert_comparison.rs:118:5
    |
 LL |     debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:57:5
+  --> $DIR/bool_assert_comparison.rs:119:5
    |
 LL |     debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:58:5
+  --> $DIR/bool_assert_comparison.rs:120:5
    |
 LL |     debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
-error: aborting due to 18 previous errors
+error: aborting due to 22 previous errors
 
diff --git a/tests/ui/box_vec.rs b/tests/ui/box_vec.rs
index 87b67c23704..1d6366972da 100644
--- a/tests/ui/box_vec.rs
+++ b/tests/ui/box_vec.rs
@@ -1,6 +1,10 @@
 #![warn(clippy::all)]
-#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
-#![allow(clippy::blacklisted_name)]
+#![allow(
+    clippy::boxed_local,
+    clippy::needless_pass_by_value,
+    clippy::blacklisted_name,
+    unused
+)]
 
 macro_rules! boxit {
     ($init:expr, $x:ty) => {
@@ -11,22 +15,22 @@ macro_rules! boxit {
 fn test_macro() {
     boxit!(Vec::new(), Vec<u8>);
 }
-pub fn test(foo: Box<Vec<bool>>) {
-    println!("{:?}", foo.get(0))
-}
+fn test(foo: Box<Vec<bool>>) {}
 
-pub fn test2(foo: Box<dyn Fn(Vec<u32>)>) {
+fn test2(foo: Box<dyn Fn(Vec<u32>)>) {
     // pass if #31 is fixed
     foo(vec![1, 2, 3])
 }
 
-pub fn test_local_not_linted() {
+fn test_local_not_linted() {
     let _: Box<Vec<bool>>;
 }
 
-fn main() {
-    test(Box::new(Vec::new()));
-    test2(Box::new(|v| println!("{:?}", v)));
-    test_macro();
-    test_local_not_linted();
+// All of these test should be allowed because they are part of the
+// public api and `avoid_breaking_exported_api` is `false` by default.
+pub fn pub_test(foo: Box<Vec<bool>>) {}
+pub fn pub_test_ret() -> Box<Vec<bool>> {
+    Box::new(Vec::new())
 }
+
+fn main() {}
diff --git a/tests/ui/box_vec.stderr b/tests/ui/box_vec.stderr
index 9b789334bae..58c1f13fb87 100644
--- a/tests/ui/box_vec.stderr
+++ b/tests/ui/box_vec.stderr
@@ -1,8 +1,8 @@
 error: you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`
-  --> $DIR/box_vec.rs:14:18
+  --> $DIR/box_vec.rs:18:14
    |
-LL | pub fn test(foo: Box<Vec<bool>>) {
-   |                  ^^^^^^^^^^^^^^
+LL | fn test(foo: Box<Vec<bool>>) {}
+   |              ^^^^^^^^^^^^^^
    |
    = note: `-D clippy::box-vec` implied by `-D warnings`
    = help: `Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation
diff --git a/tests/ui/checked_unwrap/complex_conditionals.stderr b/tests/ui/checked_unwrap/complex_conditionals.stderr
index 33bb5136ef8..46c6f69708e 100644
--- a/tests/ui/checked_unwrap/complex_conditionals.stderr
+++ b/tests/ui/checked_unwrap/complex_conditionals.stderr
@@ -1,4 +1,4 @@
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:8:9
    |
 LL |     if x.is_ok() && y.is_err() {
@@ -11,6 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
   --> $DIR/complex_conditionals.rs:9:9
@@ -36,7 +37,7 @@ LL |     if x.is_ok() && y.is_err() {
 LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `y` after checking its variant with `is_err`
   --> $DIR/complex_conditionals.rs:11:9
    |
 LL |     if x.is_ok() && y.is_err() {
@@ -44,6 +45,8 @@ LL |     if x.is_ok() && y.is_err() {
 ...
 LL |         y.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap()` will always panic
   --> $DIR/complex_conditionals.rs:25:9
@@ -54,7 +57,7 @@ LL |     if x.is_ok() || y.is_ok() {
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `x` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:26:9
    |
 LL |     if x.is_ok() || y.is_ok() {
@@ -62,6 +65,8 @@ LL |     if x.is_ok() || y.is_ok() {
 ...
 LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap()` will always panic
   --> $DIR/complex_conditionals.rs:27:9
@@ -72,7 +77,7 @@ LL |     if x.is_ok() || y.is_ok() {
 LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `y` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:28:9
    |
 LL |     if x.is_ok() || y.is_ok() {
@@ -80,14 +85,18 @@ LL |     if x.is_ok() || y.is_ok() {
 ...
 LL |         y.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:32:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
    |        --------- the check is happening here
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
   --> $DIR/complex_conditionals.rs:33:9
@@ -107,7 +116,7 @@ LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
 LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `y` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:35:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
@@ -115,8 +124,10 @@ LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
 ...
 LL |         y.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `z` after checking its variant with `is_err`
   --> $DIR/complex_conditionals.rs:36:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
@@ -124,6 +135,8 @@ LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
 ...
 LL |         z.unwrap(); // unnecessary
    |         ^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
   --> $DIR/complex_conditionals.rs:37:9
@@ -143,7 +156,7 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `x` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:46:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
@@ -151,8 +164,10 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 ...
 LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `y` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:47:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
@@ -160,6 +175,8 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 ...
 LL |         y.unwrap(); // unnecessary
    |         ^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
   --> $DIR/complex_conditionals.rs:48:9
@@ -179,7 +196,7 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 LL |         z.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `z` after checking its variant with `is_err`
   --> $DIR/complex_conditionals.rs:50:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
@@ -187,6 +204,8 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 ...
 LL |         z.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: aborting due to 20 previous errors
 
diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
index a01f7f956f6..542ab53300c 100644
--- a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
+++ b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
@@ -1,8 +1,8 @@
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_some`
   --> $DIR/complex_conditionals_nested.rs:8:13
    |
 LL |         if x.is_some() {
-   |            ----------- the check is happening here
+   |         -------------- help: try: `if let Some(..) = x`
 LL |             x.unwrap(); // unnecessary
    |             ^^^^^^^^^^
    |
diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs
index 8f23fb28827..ee3fdfabe9d 100644
--- a/tests/ui/checked_unwrap/simple_conditionals.rs
+++ b/tests/ui/checked_unwrap/simple_conditionals.rs
@@ -37,8 +37,10 @@ fn main() {
     let x = Some(());
     if x.is_some() {
         x.unwrap(); // unnecessary
+        x.expect("an error message"); // unnecessary
     } else {
         x.unwrap(); // will panic
+        x.expect("an error message"); // will panic
     }
     if x.is_none() {
         x.unwrap(); // will panic
@@ -52,9 +54,11 @@ fn main() {
     let mut x: Result<(), ()> = Ok(());
     if x.is_ok() {
         x.unwrap(); // unnecessary
+        x.expect("an error message"); // unnecessary
         x.unwrap_err(); // will panic
     } else {
         x.unwrap(); // will panic
+        x.expect("an error message"); // will panic
         x.unwrap_err(); // unnecessary
     }
     if x.is_err() {
diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr
index a4bc058fe20..82f26954380 100644
--- a/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -1,8 +1,8 @@
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_some`
   --> $DIR/simple_conditionals.rs:39:9
    |
 LL |     if x.is_some() {
-   |        ----------- the check is happening here
+   |     -------------- help: try: `if let Some(..) = x`
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
    |
@@ -12,8 +12,17 @@ note: the lint level is defined here
 LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: called `expect` on `x` after checking its variant with `is_some`
+  --> $DIR/simple_conditionals.rs:40:9
+   |
+LL |     if x.is_some() {
+   |     -------------- help: try: `if let Some(..) = x`
+LL |         x.unwrap(); // unnecessary
+LL |         x.expect("an error message"); // unnecessary
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:41:9
+  --> $DIR/simple_conditionals.rs:42:9
    |
 LL |     if x.is_some() {
    |        ----------- because of this check
@@ -27,28 +36,37 @@ note: the lint level is defined here
 LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: this call to `expect()` will always panic
+  --> $DIR/simple_conditionals.rs:43:9
+   |
+LL |     if x.is_some() {
+   |        ----------- because of this check
+...
+LL |         x.expect("an error message"); // will panic
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:44:9
+  --> $DIR/simple_conditionals.rs:46:9
    |
 LL |     if x.is_none() {
    |        ----------- because of this check
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:46:9
+error: called `unwrap` on `x` after checking its variant with `is_none`
+  --> $DIR/simple_conditionals.rs:48:9
    |
 LL |     if x.is_none() {
-   |        ----------- the check is happening here
+   |     -------------- help: try: `if let Some(..) = x`
 ...
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_some`
   --> $DIR/simple_conditionals.rs:7:13
    |
 LL |         if $a.is_some() {
-   |            ------------ the check is happening here
+   |         --------------- help: try: `if let Some(..) = x`
 LL |             $a.unwrap(); // unnecessary
    |             ^^^^^^^^^^^
 ...
@@ -57,25 +75,34 @@ LL |     m!(x);
    |
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:54:9
+error: called `unwrap` on `x` after checking its variant with `is_ok`
+  --> $DIR/simple_conditionals.rs:56:9
    |
 LL |     if x.is_ok() {
-   |        --------- the check is happening here
+   |     ------------ help: try: `if let Ok(..) = x`
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
+error: called `expect` on `x` after checking its variant with `is_ok`
+  --> $DIR/simple_conditionals.rs:57:9
+   |
+LL |     if x.is_ok() {
+   |     ------------ help: try: `if let Ok(..) = x`
+LL |         x.unwrap(); // unnecessary
+LL |         x.expect("an error message"); // unnecessary
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/simple_conditionals.rs:55:9
+  --> $DIR/simple_conditionals.rs:58:9
    |
 LL |     if x.is_ok() {
    |        --------- because of this check
-LL |         x.unwrap(); // unnecessary
+...
 LL |         x.unwrap_err(); // will panic
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:57:9
+  --> $DIR/simple_conditionals.rs:60:9
    |
 LL |     if x.is_ok() {
    |        --------- because of this check
@@ -83,43 +110,52 @@ LL |     if x.is_ok() {
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:58:9
+error: this call to `expect()` will always panic
+  --> $DIR/simple_conditionals.rs:61:9
+   |
+LL |     if x.is_ok() {
+   |        --------- because of this check
+...
+LL |         x.expect("an error message"); // will panic
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: called `unwrap_err` on `x` after checking its variant with `is_ok`
+  --> $DIR/simple_conditionals.rs:62:9
    |
 LL |     if x.is_ok() {
-   |        --------- the check is happening here
+   |     ------------ help: try: `if let Err(..) = x`
 ...
 LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:61:9
+  --> $DIR/simple_conditionals.rs:65:9
    |
 LL |     if x.is_err() {
    |        ---------- because of this check
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:62:9
+error: called `unwrap_err` on `x` after checking its variant with `is_err`
+  --> $DIR/simple_conditionals.rs:66:9
    |
 LL |     if x.is_err() {
-   |        ---------- the check is happening here
+   |     ------------- help: try: `if let Err(..) = x`
 LL |         x.unwrap(); // will panic
 LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:64:9
+error: called `unwrap` on `x` after checking its variant with `is_err`
+  --> $DIR/simple_conditionals.rs:68:9
    |
 LL |     if x.is_err() {
-   |        ---------- the check is happening here
+   |     ------------- help: try: `if let Ok(..) = x`
 ...
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/simple_conditionals.rs:65:9
+  --> $DIR/simple_conditionals.rs:69:9
    |
 LL |     if x.is_err() {
    |        ---------- because of this check
@@ -127,5 +163,5 @@ LL |     if x.is_err() {
 LL |         x.unwrap_err(); // will panic
    |         ^^^^^^^^^^^^^^
 
-error: aborting due to 13 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs
new file mode 100644
index 00000000000..336a743de72
--- /dev/null
+++ b/tests/ui/derivable_impls.rs
@@ -0,0 +1,170 @@
+use std::collections::HashMap;
+
+struct FooDefault<'a> {
+    a: bool,
+    b: i32,
+    c: u64,
+    d: Vec<i32>,
+    e: FooND1,
+    f: FooND2,
+    g: HashMap<i32, i32>,
+    h: (i32, Vec<i32>),
+    i: [Vec<i32>; 3],
+    j: [i32; 5],
+    k: Option<i32>,
+    l: &'a [i32],
+}
+
+impl std::default::Default for FooDefault<'_> {
+    fn default() -> Self {
+        Self {
+            a: false,
+            b: 0,
+            c: 0u64,
+            d: vec![],
+            e: Default::default(),
+            f: FooND2::default(),
+            g: HashMap::new(),
+            h: (0, vec![]),
+            i: [vec![], vec![], vec![]],
+            j: [0; 5],
+            k: None,
+            l: &[],
+        }
+    }
+}
+
+struct TupleDefault(bool, i32, u64);
+
+impl std::default::Default for TupleDefault {
+    fn default() -> Self {
+        Self(false, 0, 0u64)
+    }
+}
+
+struct FooND1 {
+    a: bool,
+}
+
+impl std::default::Default for FooND1 {
+    fn default() -> Self {
+        Self { a: true }
+    }
+}
+
+struct FooND2 {
+    a: i32,
+}
+
+impl std::default::Default for FooND2 {
+    fn default() -> Self {
+        Self { a: 5 }
+    }
+}
+
+struct FooNDNew {
+    a: bool,
+}
+
+impl FooNDNew {
+    fn new() -> Self {
+        Self { a: true }
+    }
+}
+
+impl Default for FooNDNew {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+struct FooNDVec(Vec<i32>);
+
+impl Default for FooNDVec {
+    fn default() -> Self {
+        Self(vec![5, 12])
+    }
+}
+
+struct StrDefault<'a>(&'a str);
+
+impl Default for StrDefault<'_> {
+    fn default() -> Self {
+        Self("")
+    }
+}
+
+#[derive(Default)]
+struct AlreadyDerived(i32, bool);
+
+macro_rules! mac {
+    () => {
+        0
+    };
+    ($e:expr) => {
+        struct X(u32);
+        impl Default for X {
+            fn default() -> Self {
+                Self($e)
+            }
+        }
+    };
+}
+
+mac!(0);
+
+struct Y(u32);
+impl Default for Y {
+    fn default() -> Self {
+        Self(mac!())
+    }
+}
+
+struct RustIssue26925<T> {
+    a: Option<T>,
+}
+
+// We should watch out for cases where a manual impl is needed because a
+// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
+// For example, a struct with Option<T> does not require T: Default, but a derive adds
+// that type bound anyways. So until #26925 get fixed we should disable lint
+// for the following case
+impl<T> Default for RustIssue26925<T> {
+    fn default() -> Self {
+        Self { a: None }
+    }
+}
+
+struct SpecializedImpl<A, B> {
+    a: A,
+    b: B,
+}
+
+impl<T: Default> Default for SpecializedImpl<T, T> {
+    fn default() -> Self {
+        Self {
+            a: T::default(),
+            b: T::default(),
+        }
+    }
+}
+
+struct WithoutSelfCurly {
+    a: bool,
+}
+
+impl Default for WithoutSelfCurly {
+    fn default() -> Self {
+        WithoutSelfCurly { a: false }
+    }
+}
+
+struct WithoutSelfParan(bool);
+
+impl Default for WithoutSelfParan {
+    fn default() -> Self {
+        WithoutSelfParan(false)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/derivable_impls.stderr b/tests/ui/derivable_impls.stderr
new file mode 100644
index 00000000000..4ed64fade02
--- /dev/null
+++ b/tests/ui/derivable_impls.stderr
@@ -0,0 +1,77 @@
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:18:1
+   |
+LL | / impl std::default::Default for FooDefault<'_> {
+LL | |     fn default() -> Self {
+LL | |         Self {
+LL | |             a: false,
+...  |
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::derivable-impls` implied by `-D warnings`
+   = help: try annotating `FooDefault` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:39:1
+   |
+LL | / impl std::default::Default for TupleDefault {
+LL | |     fn default() -> Self {
+LL | |         Self(false, 0, 0u64)
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `TupleDefault` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:91:1
+   |
+LL | / impl Default for StrDefault<'_> {
+LL | |     fn default() -> Self {
+LL | |         Self("")
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `StrDefault` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:117:1
+   |
+LL | / impl Default for Y {
+LL | |     fn default() -> Self {
+LL | |         Self(mac!())
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `Y` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:156:1
+   |
+LL | / impl Default for WithoutSelfCurly {
+LL | |     fn default() -> Self {
+LL | |         WithoutSelfCurly { a: false }
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `WithoutSelfCurly` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:164:1
+   |
+LL | / impl Default for WithoutSelfParan {
+LL | |     fn default() -> Self {
+LL | |         WithoutSelfParan(false)
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `WithoutSelfParan` with `#[derive(Default)]`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/entry.fixed b/tests/ui/entry.fixed
index cfad3090ba3..8a36ec833d7 100644
--- a/tests/ui/entry.fixed
+++ b/tests/ui/entry.fixed
@@ -4,7 +4,7 @@
 #![warn(clippy::map_entry)]
 #![feature(asm)]
 
-use std::collections::{BTreeMap, HashMap};
+use std::collections::HashMap;
 use std::hash::Hash;
 
 macro_rules! m {
@@ -142,14 +142,13 @@ fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMa
     if !m.contains_key(&k) {
         insert!(m, k, v);
     }
-}
 
-fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V, v2: V) {
-    // insert then do something, use if let
-    if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) {
-        e.insert(v);
-        foo();
-    }
+    // or_insert_with. Partial move of a local declared in the closure is ok.
+    m.entry(k).or_insert_with(|| {
+        let x = (String::new(), String::new());
+        let _ = x.0;
+        v
+    });
 }
 
 fn main() {}
diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs
index fa9280b58de..d972a201ad7 100644
--- a/tests/ui/entry.rs
+++ b/tests/ui/entry.rs
@@ -4,7 +4,7 @@
 #![warn(clippy::map_entry)]
 #![feature(asm)]
 
-use std::collections::{BTreeMap, HashMap};
+use std::collections::HashMap;
 use std::hash::Hash;
 
 macro_rules! m {
@@ -146,13 +146,12 @@ fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMa
     if !m.contains_key(&k) {
         insert!(m, k, v);
     }
-}
 
-fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V, v2: V) {
-    // insert then do something, use if let
+    // or_insert_with. Partial move of a local declared in the closure is ok.
     if !m.contains_key(&k) {
+        let x = (String::new(), String::new());
+        let _ = x.0;
         m.insert(k, v);
-        foo();
     }
 }
 
diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr
index 8f2e383d675..1076500498d 100644
--- a/tests/ui/entry.stderr
+++ b/tests/ui/entry.stderr
@@ -165,21 +165,23 @@ LL | |         m.insert(m!(k), m!(v));
 LL | |     }
    | |_____^ help: try this: `m.entry(m!(k)).or_insert_with(|| m!(v));`
 
-error: usage of `contains_key` followed by `insert` on a `BTreeMap`
-  --> $DIR/entry.rs:153:5
+error: usage of `contains_key` followed by `insert` on a `HashMap`
+  --> $DIR/entry.rs:151:5
    |
 LL | /     if !m.contains_key(&k) {
+LL | |         let x = (String::new(), String::new());
+LL | |         let _ = x.0;
 LL | |         m.insert(k, v);
-LL | |         foo();
 LL | |     }
    | |_____^
    |
 help: try this
    |
-LL ~     if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) {
-LL +         e.insert(v);
-LL +         foo();
-LL +     }
+LL ~     m.entry(k).or_insert_with(|| {
+LL +         let x = (String::new(), String::new());
+LL +         let _ = x.0;
+LL +         v
+LL +     });
    |
 
 error: aborting due to 10 previous errors
diff --git a/tests/ui/entry_btree.fixed b/tests/ui/entry_btree.fixed
new file mode 100644
index 00000000000..94979104556
--- /dev/null
+++ b/tests/ui/entry_btree.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![warn(clippy::map_entry)]
+#![allow(dead_code)]
+
+use std::collections::BTreeMap;
+
+fn foo() {}
+
+fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V) {
+    // insert then do something, use if let
+    if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) {
+        e.insert(v);
+        foo();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/entry_btree.rs b/tests/ui/entry_btree.rs
new file mode 100644
index 00000000000..080c1d959e8
--- /dev/null
+++ b/tests/ui/entry_btree.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![warn(clippy::map_entry)]
+#![allow(dead_code)]
+
+use std::collections::BTreeMap;
+
+fn foo() {}
+
+fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V) {
+    // insert then do something, use if let
+    if !m.contains_key(&k) {
+        m.insert(k, v);
+        foo();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/entry_btree.stderr b/tests/ui/entry_btree.stderr
new file mode 100644
index 00000000000..5c6fcdf1a28
--- /dev/null
+++ b/tests/ui/entry_btree.stderr
@@ -0,0 +1,20 @@
+error: usage of `contains_key` followed by `insert` on a `BTreeMap`
+  --> $DIR/entry_btree.rs:12:5
+   |
+LL | /     if !m.contains_key(&k) {
+LL | |         m.insert(k, v);
+LL | |         foo();
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::map-entry` implied by `-D warnings`
+help: try this
+   |
+LL ~     if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) {
+LL +         e.insert(v);
+LL +         foo();
+LL +     }
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/linkedlist.rs b/tests/ui/linkedlist.rs
index 2c3b25cd45e..690ea810a62 100644
--- a/tests/ui/linkedlist.rs
+++ b/tests/ui/linkedlist.rs
@@ -1,6 +1,6 @@
 #![feature(associated_type_defaults)]
 #![warn(clippy::linkedlist)]
-#![allow(dead_code, clippy::needless_pass_by_value)]
+#![allow(unused, dead_code, clippy::needless_pass_by_value)]
 
 extern crate alloc;
 use alloc::collections::linked_list::LinkedList;
@@ -20,24 +20,29 @@ impl Foo for LinkedList<u8> {
     const BAR: Option<LinkedList<u8>> = None;
 }
 
-struct Bar;
+pub struct Bar {
+    priv_linked_list_field: LinkedList<u8>,
+    pub pub_linked_list_field: LinkedList<u8>,
+}
 impl Bar {
     fn foo(_: LinkedList<u8>) {}
 }
 
-pub fn test(my_favourite_linked_list: LinkedList<u8>) {
-    println!("{:?}", my_favourite_linked_list)
-}
-
-pub fn test_ret() -> Option<LinkedList<u8>> {
-    unimplemented!();
+// All of these test should be trigger the lint because they are not
+// part of the public api
+fn test(my_favorite_linked_list: LinkedList<u8>) {}
+fn test_ret() -> Option<LinkedList<u8>> {
+    None
 }
-
-pub fn test_local_not_linted() {
+fn test_local_not_linted() {
     let _: LinkedList<u8>;
 }
 
-fn main() {
-    test(LinkedList::new());
-    test_local_not_linted();
+// All of these test should be allowed because they are part of the
+// public api and `avoid_breaking_exported_api` is `false` by default.
+pub fn pub_test(the_most_awesome_linked_list: LinkedList<u8>) {}
+pub fn pub_test_ret() -> Option<LinkedList<u8>> {
+    None
 }
+
+fn main() {}
diff --git a/tests/ui/linkedlist.stderr b/tests/ui/linkedlist.stderr
index 38ae71714d6..51327df1321 100644
--- a/tests/ui/linkedlist.stderr
+++ b/tests/ui/linkedlist.stderr
@@ -40,7 +40,15 @@ LL |     const BAR: Option<LinkedList<u8>>;
    = help: a `VecDeque` might work
 
 error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
-  --> $DIR/linkedlist.rs:25:15
+  --> $DIR/linkedlist.rs:24:29
+   |
+LL |     priv_linked_list_field: LinkedList<u8>,
+   |                             ^^^^^^^^^^^^^^
+   |
+   = help: a `VecDeque` might work
+
+error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
+  --> $DIR/linkedlist.rs:28:15
    |
 LL |     fn foo(_: LinkedList<u8>) {}
    |               ^^^^^^^^^^^^^^
@@ -48,20 +56,20 @@ LL |     fn foo(_: LinkedList<u8>) {}
    = help: a `VecDeque` might work
 
 error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
-  --> $DIR/linkedlist.rs:28:39
+  --> $DIR/linkedlist.rs:33:34
    |
-LL | pub fn test(my_favourite_linked_list: LinkedList<u8>) {
-   |                                       ^^^^^^^^^^^^^^
+LL | fn test(my_favorite_linked_list: LinkedList<u8>) {}
+   |                                  ^^^^^^^^^^^^^^
    |
    = help: a `VecDeque` might work
 
 error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
-  --> $DIR/linkedlist.rs:32:29
+  --> $DIR/linkedlist.rs:34:25
    |
-LL | pub fn test_ret() -> Option<LinkedList<u8>> {
-   |                             ^^^^^^^^^^^^^^
+LL | fn test_ret() -> Option<LinkedList<u8>> {
+   |                         ^^^^^^^^^^^^^^
    |
    = help: a `VecDeque` might work
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/manual_flatten.rs b/tests/ui/manual_flatten.rs
index b5bd35a6878..7db6b730963 100644
--- a/tests/ui/manual_flatten.rs
+++ b/tests/ui/manual_flatten.rs
@@ -91,6 +91,19 @@ fn main() {
         }
     }
 
+    struct Test {
+        a: usize,
+    }
+
+    let mut vec_of_struct = [Some(Test { a: 1 }), None];
+
+    // Usage of `if let` expression should not trigger lint
+    for n in vec_of_struct.iter_mut() {
+        if let Some(z) = n {
+            *n = None;
+        }
+    }
+
     // Using manual flatten should not trigger the lint
     for n in vec![Some(1), Some(2), Some(3)].iter().flatten() {
         println!("{}", n);
diff --git a/tests/ui/manual_map_option_2.fixed b/tests/ui/manual_map_option_2.fixed
new file mode 100644
index 00000000000..8cc12149403
--- /dev/null
+++ b/tests/ui/manual_map_option_2.fixed
@@ -0,0 +1,50 @@
+// run-rustfix
+
+#![warn(clippy::manual_map)]
+#![allow(clippy::toplevel_ref_arg)]
+
+fn main() {
+    // Lint. `y` is declared within the arm, so it isn't captured by the map closure
+    let _ = Some(0).map(|x| {
+            let y = (String::new(), String::new());
+            (x, y.0)
+        });
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured by the map
+    // closure
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some((x.clone(), s)),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured by the map
+    // closure
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            let clone = x.clone();
+            let s = || s;
+            (clone, s())
+        }),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured as a mutable
+    // reference by the map closure
+    let mut s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            let clone = x.clone();
+            let ref mut s = s;
+            (clone, s)
+        }),
+        None => None,
+    };
+
+    // Lint. `s` is captured by reference, so no lifetime issues.
+    let s = Some(String::new());
+    let _ = s.as_ref().map(|x| {
+            if let Some(ref s) = s { (x.clone(), s) } else { panic!() }
+        });
+}
diff --git a/tests/ui/manual_map_option_2.rs b/tests/ui/manual_map_option_2.rs
new file mode 100644
index 00000000000..0862b201ead
--- /dev/null
+++ b/tests/ui/manual_map_option_2.rs
@@ -0,0 +1,56 @@
+// run-rustfix
+
+#![warn(clippy::manual_map)]
+#![allow(clippy::toplevel_ref_arg)]
+
+fn main() {
+    // Lint. `y` is declared within the arm, so it isn't captured by the map closure
+    let _ = match Some(0) {
+        Some(x) => Some({
+            let y = (String::new(), String::new());
+            (x, y.0)
+        }),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured by the map
+    // closure
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some((x.clone(), s)),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured by the map
+    // closure
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            let clone = x.clone();
+            let s = || s;
+            (clone, s())
+        }),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured as a mutable
+    // reference by the map closure
+    let mut s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            let clone = x.clone();
+            let ref mut s = s;
+            (clone, s)
+        }),
+        None => None,
+    };
+
+    // Lint. `s` is captured by reference, so no lifetime issues.
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            if let Some(ref s) = s { (x.clone(), s) } else { panic!() }
+        }),
+        None => None,
+    };
+}
diff --git a/tests/ui/manual_map_option_2.stderr b/tests/ui/manual_map_option_2.stderr
new file mode 100644
index 00000000000..711ff6c4a4b
--- /dev/null
+++ b/tests/ui/manual_map_option_2.stderr
@@ -0,0 +1,43 @@
+error: manual implementation of `Option::map`
+  --> $DIR/manual_map_option_2.rs:8:13
+   |
+LL |       let _ = match Some(0) {
+   |  _____________^
+LL | |         Some(x) => Some({
+LL | |             let y = (String::new(), String::new());
+LL | |             (x, y.0)
+LL | |         }),
+LL | |         None => None,
+LL | |     };
+   | |_____^
+   |
+   = note: `-D clippy::manual-map` implied by `-D warnings`
+help: try this
+   |
+LL ~     let _ = Some(0).map(|x| {
+LL +             let y = (String::new(), String::new());
+LL +             (x, y.0)
+LL ~         });
+   |
+
+error: manual implementation of `Option::map`
+  --> $DIR/manual_map_option_2.rs:50:13
+   |
+LL |       let _ = match &s {
+   |  _____________^
+LL | |         Some(x) => Some({
+LL | |             if let Some(ref s) = s { (x.clone(), s) } else { panic!() }
+LL | |         }),
+LL | |         None => None,
+LL | |     };
+   | |_____^
+   |
+help: try this
+   |
+LL ~     let _ = s.as_ref().map(|x| {
+LL +             if let Some(ref s) = s { (x.clone(), s) } else { panic!() }
+LL ~         });
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/manual_split_once.fixed b/tests/ui/manual_split_once.fixed
new file mode 100644
index 00000000000..3a0332939d4
--- /dev/null
+++ b/tests/ui/manual_split_once.fixed
@@ -0,0 +1,50 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_split_once)]
+#![allow(clippy::iter_skip_next, clippy::iter_nth_zero)]
+
+extern crate itertools;
+
+#[allow(unused_imports)]
+use itertools::Itertools;
+
+fn main() {
+    let _ = Some("key=value".split_once('=').map_or("key=value", |x| x.0));
+    let _ = "key=value".splitn(2, '=').nth(2);
+    let _ = "key=value".split_once('=').map_or("key=value", |x| x.0);
+    let _ = "key=value".split_once('=').map_or("key=value", |x| x.0);
+    let _ = "key=value".split_once('=').unwrap().1;
+    let _ = "key=value".split_once('=').unwrap().1;
+    let (_, _) = "key=value".split_once('=').unwrap();
+
+    let s = String::from("key=value");
+    let _ = s.split_once('=').map_or(&*s, |x| x.0);
+
+    let s = Box::<str>::from("key=value");
+    let _ = s.split_once('=').map_or(&*s, |x| x.0);
+
+    let s = &"key=value";
+    let _ = s.split_once('=').map_or(*s, |x| x.0);
+
+    fn _f(s: &str) -> Option<&str> {
+        let _ = s.split_once("key=value").map_or(s, |x| x.0);
+        let _ = s.split_once("key=value")?.1;
+        let _ = s.split_once("key=value")?.1;
+        None
+    }
+
+    // Don't lint, slices don't have `split_once`
+    let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
+}
+
+fn _msrv_1_51() {
+    #![clippy::msrv = "1.51"]
+    // `str::split_once` was stabilized in 1.16. Do not lint this
+    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+}
+
+fn _msrv_1_52() {
+    #![clippy::msrv = "1.52"]
+    let _ = "key=value".split_once('=').unwrap().1;
+}
diff --git a/tests/ui/manual_split_once.rs b/tests/ui/manual_split_once.rs
new file mode 100644
index 00000000000..e6093b63fe8
--- /dev/null
+++ b/tests/ui/manual_split_once.rs
@@ -0,0 +1,50 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_split_once)]
+#![allow(clippy::iter_skip_next, clippy::iter_nth_zero)]
+
+extern crate itertools;
+
+#[allow(unused_imports)]
+use itertools::Itertools;
+
+fn main() {
+    let _ = "key=value".splitn(2, '=').next();
+    let _ = "key=value".splitn(2, '=').nth(2);
+    let _ = "key=value".splitn(2, '=').next().unwrap();
+    let _ = "key=value".splitn(2, '=').nth(0).unwrap();
+    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+    let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
+    let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
+
+    let s = String::from("key=value");
+    let _ = s.splitn(2, '=').next().unwrap();
+
+    let s = Box::<str>::from("key=value");
+    let _ = s.splitn(2, '=').nth(0).unwrap();
+
+    let s = &"key=value";
+    let _ = s.splitn(2, '=').skip(0).next().unwrap();
+
+    fn _f(s: &str) -> Option<&str> {
+        let _ = s.splitn(2, "key=value").next()?;
+        let _ = s.splitn(2, "key=value").nth(1)?;
+        let _ = s.splitn(2, "key=value").skip(1).next()?;
+        None
+    }
+
+    // Don't lint, slices don't have `split_once`
+    let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
+}
+
+fn _msrv_1_51() {
+    #![clippy::msrv = "1.51"]
+    // `str::split_once` was stabilized in 1.16. Do not lint this
+    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+}
+
+fn _msrv_1_52() {
+    #![clippy::msrv = "1.52"]
+    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+}
diff --git a/tests/ui/manual_split_once.stderr b/tests/ui/manual_split_once.stderr
new file mode 100644
index 00000000000..4f15196b469
--- /dev/null
+++ b/tests/ui/manual_split_once.stderr
@@ -0,0 +1,82 @@
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:13:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').next();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some("key=value".split_once('=').map_or("key=value", |x| x.0))`
+   |
+   = note: `-D clippy::manual-split-once` implied by `-D warnings`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:15:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').map_or("key=value", |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:16:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').nth(0).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').map_or("key=value", |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:17:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:18:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:19:18
+   |
+LL |     let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=')`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:22:13
+   |
+LL |     let _ = s.splitn(2, '=').next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(&*s, |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:25:13
+   |
+LL |     let _ = s.splitn(2, '=').nth(0).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(&*s, |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:28:13
+   |
+LL |     let _ = s.splitn(2, '=').skip(0).next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(*s, |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:31:17
+   |
+LL |         let _ = s.splitn(2, "key=value").next()?;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value").map_or(s, |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:32:17
+   |
+LL |         let _ = s.splitn(2, "key=value").nth(1)?;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value")?.1`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:33:17
+   |
+LL |         let _ = s.splitn(2, "key=value").skip(1).next()?;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value")?.1`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:49:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
+
+error: aborting due to 13 previous errors
+
diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed
index 3b6224254a0..b609ba65946 100644
--- a/tests/ui/mem_replace.fixed
+++ b/tests/ui/mem_replace.fixed
@@ -51,9 +51,29 @@ fn replace_with_default() {
 
     let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new();
     let _ = std::mem::take(&mut binary_heap);
+
+    let mut tuple = (vec![1, 2], BinaryHeap::<i32>::new());
+    let _ = std::mem::take(&mut tuple);
+
+    let mut refstr = "hello";
+    let _ = std::mem::take(&mut refstr);
+
+    let mut slice: &[i32] = &[1, 2, 3];
+    let _ = std::mem::take(&mut slice);
+}
+
+// lint is disabled for primitives because in this case `take`
+// has no clear benefit over `replace` and sometimes is harder to read
+fn dont_lint_primitive() {
+    let mut pbool = true;
+    let _ = std::mem::replace(&mut pbool, false);
+
+    let mut pint = 5;
+    let _ = std::mem::replace(&mut pint, 0);
 }
 
 fn main() {
     replace_option_with_none();
     replace_with_default();
+    dont_lint_primitive();
 }
diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs
index 0a36db9e921..93f6dcdec83 100644
--- a/tests/ui/mem_replace.rs
+++ b/tests/ui/mem_replace.rs
@@ -51,9 +51,29 @@ fn replace_with_default() {
 
     let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new();
     let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
+
+    let mut tuple = (vec![1, 2], BinaryHeap::<i32>::new());
+    let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new()));
+
+    let mut refstr = "hello";
+    let _ = std::mem::replace(&mut refstr, "");
+
+    let mut slice: &[i32] = &[1, 2, 3];
+    let _ = std::mem::replace(&mut slice, &[]);
+}
+
+// lint is disabled for primitives because in this case `take`
+// has no clear benefit over `replace` and sometimes is harder to read
+fn dont_lint_primitive() {
+    let mut pbool = true;
+    let _ = std::mem::replace(&mut pbool, false);
+
+    let mut pint = 5;
+    let _ = std::mem::replace(&mut pint, 0);
 }
 
 fn main() {
     replace_option_with_none();
     replace_with_default();
+    dont_lint_primitive();
 }
diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr
index f8aa1538bff..90dc6c95f85 100644
--- a/tests/ui/mem_replace.stderr
+++ b/tests/ui/mem_replace.stderr
@@ -98,5 +98,23 @@ error: replacing a value of type `T` with `T::default()` is better expressed usi
 LL |     let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)`
 
-error: aborting due to 16 previous errors
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:56:13
+   |
+LL |     let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new()));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut tuple)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:59:13
+   |
+LL |     let _ = std::mem::replace(&mut refstr, "");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut refstr)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:62:13
+   |
+LL |     let _ = std::mem::replace(&mut slice, &[]);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut slice)`
+
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs
index 513d930e056..c441b35b992 100644
--- a/tests/ui/methods.rs
+++ b/tests/ui/methods.rs
@@ -32,7 +32,7 @@ use std::ops::Mul;
 use std::rc::{self, Rc};
 use std::sync::{self, Arc};
 
-use option_helpers::IteratorFalsePositives;
+use option_helpers::{IteratorFalsePositives, IteratorMethodFalsePositives};
 
 struct Lt<'a> {
     foo: &'a u32,
@@ -131,6 +131,9 @@ fn filter_next() {
     // Check that we don't lint if the caller is not an `Iterator`.
     let foo = IteratorFalsePositives { foo: 0 };
     let _ = foo.filter().next();
+
+    let foo = IteratorMethodFalsePositives {};
+    let _ = foo.filter(42).next();
 }
 
 fn main() {
diff --git a/tests/ui/min_rust_version_attr.rs b/tests/ui/min_rust_version_attr.rs
index 7f9f7ddc535..8d9fc5a864d 100644
--- a/tests/ui/min_rust_version_attr.rs
+++ b/tests/ui/min_rust_version_attr.rs
@@ -4,6 +4,11 @@
 
 use std::ops::{Deref, RangeFrom};
 
+fn approx_const() {
+    let log2_10 = 3.321928094887362;
+    let log10_2 = 0.301029995663981;
+}
+
 fn cloned_instead_of_copied() {
     let _ = [1].iter().cloned();
 }
diff --git a/tests/ui/min_rust_version_attr.stderr b/tests/ui/min_rust_version_attr.stderr
index a2e4e86ed6b..360dcfb230c 100644
--- a/tests/ui/min_rust_version_attr.stderr
+++ b/tests/ui/min_rust_version_attr.stderr
@@ -1,12 +1,12 @@
 error: stripping a prefix manually
-  --> $DIR/min_rust_version_attr.rs:160:24
+  --> $DIR/min_rust_version_attr.rs:165:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::manual-strip` implied by `-D warnings`
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:159:9
+  --> $DIR/min_rust_version_attr.rs:164:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,13 +17,13 @@ LL ~             assert_eq!(<stripped>.to_uppercase(), "WORLD!");
    |
 
 error: stripping a prefix manually
-  --> $DIR/min_rust_version_attr.rs:172:24
+  --> $DIR/min_rust_version_attr.rs:177:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:171:9
+  --> $DIR/min_rust_version_attr.rs:176:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/missing-doc-crate.stderr b/tests/ui/missing-doc-crate.stderr
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/tests/ui/missing-doc-crate.stderr
+++ /dev/null
diff --git a/tests/ui/missing_const_for_fn/cant_be_const.stderr b/tests/ui/missing_const_for_fn/cant_be_const.stderr
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/tests/ui/missing_const_for_fn/cant_be_const.stderr
+++ /dev/null
diff --git a/tests/ui/needless_option_as_deref.fixed b/tests/ui/needless_option_as_deref.fixed
new file mode 100644
index 00000000000..d721452ae88
--- /dev/null
+++ b/tests/ui/needless_option_as_deref.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+
+#[warn(clippy::needless_option_as_deref)]
+
+fn main() {
+    // should lint
+    let _: Option<&usize> = Some(&1);
+    let _: Option<&mut usize> = Some(&mut 1);
+
+    // should not lint
+    let _ = Some(Box::new(1)).as_deref();
+    let _ = Some(Box::new(1)).as_deref_mut();
+}
diff --git a/tests/ui/needless_option_as_deref.rs b/tests/ui/needless_option_as_deref.rs
new file mode 100644
index 00000000000..bb15512adf6
--- /dev/null
+++ b/tests/ui/needless_option_as_deref.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+
+#[warn(clippy::needless_option_as_deref)]
+
+fn main() {
+    // should lint
+    let _: Option<&usize> = Some(&1).as_deref();
+    let _: Option<&mut usize> = Some(&mut 1).as_deref_mut();
+
+    // should not lint
+    let _ = Some(Box::new(1)).as_deref();
+    let _ = Some(Box::new(1)).as_deref_mut();
+}
diff --git a/tests/ui/needless_option_as_deref.stderr b/tests/ui/needless_option_as_deref.stderr
new file mode 100644
index 00000000000..5dd507b4a71
--- /dev/null
+++ b/tests/ui/needless_option_as_deref.stderr
@@ -0,0 +1,16 @@
+error: derefed type is same as origin
+  --> $DIR/needless_option_as_deref.rs:7:29
+   |
+LL |     let _: Option<&usize> = Some(&1).as_deref();
+   |                             ^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&1)`
+   |
+   = note: `-D clippy::needless-option-as-deref` implied by `-D warnings`
+
+error: derefed type is same as origin
+  --> $DIR/needless_option_as_deref.rs:8:33
+   |
+LL |     let _: Option<&mut usize> = Some(&mut 1).as_deref_mut();
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&mut 1)`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed
index 769ccc14bc1..d1815d0aec3 100644
--- a/tests/ui/option_if_let_else.fixed
+++ b/tests/ui/option_if_let_else.fixed
@@ -1,3 +1,4 @@
+// edition:2018
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure)]
@@ -86,4 +87,65 @@ fn main() {
     test_map_or_else(None);
     let _ = negative_tests(None);
     let _ = impure_else(None);
+
+    let _ = Some(0).map_or(0, |x| loop {
+            if x == 0 {
+                break x;
+            }
+        });
+
+    // #7576
+    const fn _f(x: Option<u32>) -> u32 {
+        // Don't lint, `map_or` isn't const
+        if let Some(x) = x { x } else { 10 }
+    }
+
+    // #5822
+    let s = String::new();
+    // Don't lint, `Some` branch consumes `s`, but else branch uses `s`
+    let _ = if let Some(x) = Some(0) {
+        let s = s;
+        s.len() + x
+    } else {
+        s.len()
+    };
+
+    let s = String::new();
+    // Lint, both branches immutably borrow `s`.
+    let _ = Some(0).map_or_else(|| s.len(), |x| s.len() + x);
+
+    let s = String::new();
+    // Lint, `Some` branch consumes `s`, but else branch doesn't use `s`.
+    let _ = Some(0).map_or(1, |x| {
+        let s = s;
+        s.len() + x
+    });
+
+    let s = Some(String::new());
+    // Don't lint, `Some` branch borrows `s`, but else branch consumes `s`
+    let _ = if let Some(x) = &s {
+        x.len()
+    } else {
+        let _s = s;
+        10
+    };
+
+    let mut s = Some(String::new());
+    // Don't lint, `Some` branch mutably borrows `s`, but else branch also borrows  `s`
+    let _ = if let Some(x) = &mut s {
+        x.push_str("test");
+        x.len()
+    } else {
+        let _s = &s;
+        10
+    };
+
+    async fn _f1(x: u32) -> u32 {
+        x
+    }
+
+    async fn _f2() {
+        // Don't lint. `await` can't be moved into a closure.
+        let _ = if let Some(x) = Some(0) { _f1(x).await } else { 0 };
+    }
 }
diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs
index e2f8dec3b93..a15627338cb 100644
--- a/tests/ui/option_if_let_else.rs
+++ b/tests/ui/option_if_let_else.rs
@@ -1,3 +1,4 @@
+// edition:2018
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure)]
@@ -105,4 +106,71 @@ fn main() {
     test_map_or_else(None);
     let _ = negative_tests(None);
     let _ = impure_else(None);
+
+    let _ = if let Some(x) = Some(0) {
+        loop {
+            if x == 0 {
+                break x;
+            }
+        }
+    } else {
+        0
+    };
+
+    // #7576
+    const fn _f(x: Option<u32>) -> u32 {
+        // Don't lint, `map_or` isn't const
+        if let Some(x) = x { x } else { 10 }
+    }
+
+    // #5822
+    let s = String::new();
+    // Don't lint, `Some` branch consumes `s`, but else branch uses `s`
+    let _ = if let Some(x) = Some(0) {
+        let s = s;
+        s.len() + x
+    } else {
+        s.len()
+    };
+
+    let s = String::new();
+    // Lint, both branches immutably borrow `s`.
+    let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
+
+    let s = String::new();
+    // Lint, `Some` branch consumes `s`, but else branch doesn't use `s`.
+    let _ = if let Some(x) = Some(0) {
+        let s = s;
+        s.len() + x
+    } else {
+        1
+    };
+
+    let s = Some(String::new());
+    // Don't lint, `Some` branch borrows `s`, but else branch consumes `s`
+    let _ = if let Some(x) = &s {
+        x.len()
+    } else {
+        let _s = s;
+        10
+    };
+
+    let mut s = Some(String::new());
+    // Don't lint, `Some` branch mutably borrows `s`, but else branch also borrows  `s`
+    let _ = if let Some(x) = &mut s {
+        x.push_str("test");
+        x.len()
+    } else {
+        let _s = &s;
+        10
+    };
+
+    async fn _f1(x: u32) -> u32 {
+        x
+    }
+
+    async fn _f2() {
+        // Don't lint. `await` can't be moved into a closure.
+        let _ = if let Some(x) = Some(0) { _f1(x).await } else { 0 };
+    }
 }
diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr
index 099e49ef8e3..ed748ee8b39 100644
--- a/tests/ui/option_if_let_else.stderr
+++ b/tests/ui/option_if_let_else.stderr
@@ -1,5 +1,5 @@
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:7:5
+  --> $DIR/option_if_let_else.rs:8:5
    |
 LL | /     if let Some(x) = string {
 LL | |         (true, x)
@@ -11,19 +11,19 @@ LL | |     }
    = note: `-D clippy::option-if-let-else` implied by `-D warnings`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:25:13
+  --> $DIR/option_if_let_else.rs:26:13
    |
 LL |     let _ = if let Some(s) = *string { s.len() } else { 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:26:13
+  --> $DIR/option_if_let_else.rs:27:13
    |
 LL |     let _ = if let Some(s) = &num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:27:13
+  --> $DIR/option_if_let_else.rs:28:13
    |
 LL |       let _ = if let Some(s) = &mut num {
    |  _____________^
@@ -43,13 +43,13 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:33:13
+  --> $DIR/option_if_let_else.rs:34:13
    |
 LL |     let _ = if let Some(ref s) = num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:34:13
+  --> $DIR/option_if_let_else.rs:35:13
    |
 LL |       let _ = if let Some(mut s) = num {
    |  _____________^
@@ -69,7 +69,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:40:13
+  --> $DIR/option_if_let_else.rs:41:13
    |
 LL |       let _ = if let Some(ref mut s) = num {
    |  _____________^
@@ -89,7 +89,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:49:5
+  --> $DIR/option_if_let_else.rs:50:5
    |
 LL | /     if let Some(x) = arg {
 LL | |         let y = x * x;
@@ -108,7 +108,7 @@ LL +     })
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:62:13
+  --> $DIR/option_if_let_else.rs:63:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -120,7 +120,7 @@ LL | |     };
    | |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)`
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:71:13
+  --> $DIR/option_if_let_else.rs:72:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -143,10 +143,58 @@ LL ~     }, |x| x * x * x * x);
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:100:13
+  --> $DIR/option_if_let_else.rs:101:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
-error: aborting due to 11 previous errors
+error: use Option::map_or instead of an if let/else
+  --> $DIR/option_if_let_else.rs:110:13
+   |
+LL |       let _ = if let Some(x) = Some(0) {
+   |  _____________^
+LL | |         loop {
+LL | |             if x == 0 {
+LL | |                 break x;
+...  |
+LL | |         0
+LL | |     };
+   | |_____^
+   |
+help: try
+   |
+LL ~     let _ = Some(0).map_or(0, |x| loop {
+LL +             if x == 0 {
+LL +                 break x;
+LL +             }
+LL ~         });
+   |
+
+error: use Option::map_or_else instead of an if let/else
+  --> $DIR/option_if_let_else.rs:138:13
+   |
+LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or_else(|| s.len(), |x| s.len() + x)`
+
+error: use Option::map_or instead of an if let/else
+  --> $DIR/option_if_let_else.rs:142:13
+   |
+LL |       let _ = if let Some(x) = Some(0) {
+   |  _____________^
+LL | |         let s = s;
+LL | |         s.len() + x
+LL | |     } else {
+LL | |         1
+LL | |     };
+   | |_____^
+   |
+help: try
+   |
+LL ~     let _ = Some(0).map_or(1, |x| {
+LL +         let s = s;
+LL +         s.len() + x
+LL ~     });
+   |
+
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui/proc_macro.stderr b/tests/ui/proc_macro.stderr
index 872cbc66af6..48fd58c9a49 100644
--- a/tests/ui/proc_macro.stderr
+++ b/tests/ui/proc_macro.stderr
@@ -1,10 +1,11 @@
-error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::PI` found
   --> $DIR/proc_macro.rs:10:14
    |
 LL |     let _x = 3.14;
    |              ^^^^
    |
    = note: `#[deny(clippy::approx_constant)]` on by default
+   = help: consider using the constant directly
 
 error: aborting due to previous error
 
diff --git a/tests/ui/rc_buffer_redefined_string.stderr b/tests/ui/rc_buffer_redefined_string.stderr
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/tests/ui/rc_buffer_redefined_string.stderr
+++ /dev/null
diff --git a/tests/ui/rc_mutex.rs b/tests/ui/rc_mutex.rs
index 657a3ecf6a0..18e8a2e01e0 100644
--- a/tests/ui/rc_mutex.rs
+++ b/tests/ui/rc_mutex.rs
@@ -1,13 +1,17 @@
 #![warn(clippy::rc_mutex)]
-#![allow(clippy::blacklisted_name)]
+#![allow(unused, clippy::blacklisted_name)]
 
 use std::rc::Rc;
 use std::sync::Mutex;
 
-pub struct MyStruct {
+pub struct MyStructWithPrivItem {
     foo: Rc<Mutex<i32>>,
 }
 
+pub struct MyStructWithPubItem {
+    pub foo: Rc<Mutex<i32>>,
+}
+
 pub struct SubT<T> {
     foo: T,
 }
@@ -17,18 +21,16 @@ pub enum MyEnum {
     Two,
 }
 
-pub fn test1<T>(foo: Rc<Mutex<T>>) {}
-
-pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
+// All of these test should be trigger the lint because they are not
+// part of the public api
+fn test1<T>(foo: Rc<Mutex<T>>) {}
+fn test2(foo: Rc<Mutex<MyEnum>>) {}
+fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
 
-pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
+// All of these test should be allowed because they are part of the
+// public api and `avoid_breaking_exported_api` is `false` by default.
+pub fn pub_test1<T>(foo: Rc<Mutex<T>>) {}
+pub fn pub_test2(foo: Rc<Mutex<MyEnum>>) {}
+pub fn pub_test3(foo: Rc<Mutex<SubT<usize>>>) {}
 
-fn main() {
-    test1(Rc::new(Mutex::new(1)));
-    test2(Rc::new(Mutex::new(MyEnum::One)));
-    test3(Rc::new(Mutex::new(SubT { foo: 1 })));
-
-    let _my_struct = MyStruct {
-        foo: Rc::new(Mutex::new(1)),
-    };
-}
+fn main() {}
diff --git a/tests/ui/rc_mutex.stderr b/tests/ui/rc_mutex.stderr
index 8e58e2bc2d0..fe84361d781 100644
--- a/tests/ui/rc_mutex.stderr
+++ b/tests/ui/rc_mutex.stderr
@@ -1,28 +1,35 @@
-error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
+error: usage of `Rc<Mutex<_>>`
   --> $DIR/rc_mutex.rs:8:10
    |
 LL |     foo: Rc<Mutex<i32>>,
    |          ^^^^^^^^^^^^^^
    |
    = note: `-D clippy::rc-mutex` implied by `-D warnings`
+   = help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
 
-error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
-  --> $DIR/rc_mutex.rs:20:22
+error: usage of `Rc<Mutex<_>>`
+  --> $DIR/rc_mutex.rs:26:18
    |
-LL | pub fn test1<T>(foo: Rc<Mutex<T>>) {}
-   |                      ^^^^^^^^^^^^
+LL | fn test1<T>(foo: Rc<Mutex<T>>) {}
+   |                  ^^^^^^^^^^^^
+   |
+   = help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
 
-error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
-  --> $DIR/rc_mutex.rs:22:19
+error: usage of `Rc<Mutex<_>>`
+  --> $DIR/rc_mutex.rs:27:15
+   |
+LL | fn test2(foo: Rc<Mutex<MyEnum>>) {}
+   |               ^^^^^^^^^^^^^^^^^
    |
-LL | pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
-   |                   ^^^^^^^^^^^^^^^^^
+   = help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
 
-error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
-  --> $DIR/rc_mutex.rs:24:19
+error: usage of `Rc<Mutex<_>>`
+  --> $DIR/rc_mutex.rs:28:15
+   |
+LL | fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^
    |
-LL | pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^
+   = help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/redundant_allocation.rs b/tests/ui/redundant_allocation.rs
index 1b4f2a66c70..52fbc91e325 100644
--- a/tests/ui/redundant_allocation.rs
+++ b/tests/ui/redundant_allocation.rs
@@ -77,4 +77,24 @@ mod outer_arc {
     }
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/7487
+mod box_dyn {
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    pub trait T {}
+
+    struct S {
+        a: Box<Box<dyn T>>,
+        b: Rc<Box<dyn T>>,
+        c: Arc<Box<dyn T>>,
+    }
+
+    pub fn test_box(_: Box<Box<dyn T>>) {}
+    pub fn test_rc(_: Rc<Box<dyn T>>) {}
+    pub fn test_arc(_: Arc<Box<dyn T>>) {}
+    pub fn test_rc_box(_: Rc<Box<Box<dyn T>>>) {}
+}
+
 fn main() {}
diff --git a/tests/ui/redundant_allocation.stderr b/tests/ui/redundant_allocation.stderr
index fdab74eb538..c3b10e5f5e6 100644
--- a/tests/ui/redundant_allocation.stderr
+++ b/tests/ui/redundant_allocation.stderr
@@ -134,5 +134,14 @@ LL |     pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
    = note: `Rc<SubT<T>>` is already on the heap, `Arc<Rc<SubT<T>>>` makes an extra allocation
    = help: consider using just `Arc<SubT<T>>` or `Rc<SubT<T>>`
 
-error: aborting due to 15 previous errors
+error: usage of `Rc<Box<Box<dyn T>>>`
+  --> $DIR/redundant_allocation.rs:97:27
+   |
+LL |     pub fn test_rc_box(_: Rc<Box<Box<dyn T>>>) {}
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Box<Box<dyn T>>` is already on the heap, `Rc<Box<Box<dyn T>>>` makes an extra allocation
+   = help: consider using just `Rc<Box<dyn T>>` or `Box<Box<dyn T>>`
+
+error: aborting due to 16 previous errors
 
diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs
index b4a931043b0..ac4c1bc6597 100644
--- a/tests/ui/temporary_assignment.rs
+++ b/tests/ui/temporary_assignment.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::temporary_assignment)]
-#![allow(const_item_mutation)]
 
 use std::ops::{Deref, DerefMut};
 
diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr
index 4cc32c79f05..7d79901a28d 100644
--- a/tests/ui/temporary_assignment.stderr
+++ b/tests/ui/temporary_assignment.stderr
@@ -1,5 +1,5 @@
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:48:5
+  --> $DIR/temporary_assignment.rs:47:5
    |
 LL |     Struct { field: 0 }.field = 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     Struct { field: 0 }.field = 1;
    = note: `-D clippy::temporary-assignment` implied by `-D warnings`
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:49:5
+  --> $DIR/temporary_assignment.rs:48:5
    |
 LL | /     MultiStruct {
 LL | |         structure: Struct { field: 0 },
@@ -17,13 +17,13 @@ LL | |     .field = 1;
    | |______________^
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:54:5
+  --> $DIR/temporary_assignment.rs:53:5
    |
 LL |     ArrayStruct { array: [0] }.array[0] = 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:55:5
+  --> $DIR/temporary_assignment.rs:54:5
    |
 LL |     (0, 0).0 = 1;
    |     ^^^^^^^^^^^^
diff --git a/tests/ui/unnecessary_operation.fixed b/tests/ui/unnecessary_operation.fixed
index 2fca96c4cd5..bf0ec8deb34 100644
--- a/tests/ui/unnecessary_operation.fixed
+++ b/tests/ui/unnecessary_operation.fixed
@@ -62,10 +62,10 @@ fn main() {
     get_number();
     5;get_number();
     42;get_number();
-    [42, 55];get_usize();
+    assert!([42, 55].len() > get_usize());
     42;get_number();
     get_number();
-    [42; 55];get_usize();
+    assert!([42; 55].len() > get_usize());
     get_number();
     String::from("blah");
 
diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr
index f88c9f9908b..f66d08ecb82 100644
--- a/tests/ui/unnecessary_operation.stderr
+++ b/tests/ui/unnecessary_operation.stderr
@@ -1,128 +1,128 @@
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:51:5
    |
 LL |     Tuple(get_number());
-   |     ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
    |
    = note: `-D clippy::unnecessary-operation` implied by `-D warnings`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:52:5
    |
 LL |     Struct { field: get_number() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:53:5
    |
 LL |     Struct { ..get_struct() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:54:5
    |
 LL |     Enum::Tuple(get_number());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:55:5
    |
 LL |     Enum::Struct { field: get_number() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:56:5
    |
 LL |     5 + get_number();
-   |     ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();`
+   |     ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:57:5
    |
 LL |     *&get_number();
-   |     ^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:58:5
    |
 LL |     &get_number();
-   |     ^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:59:5
    |
 LL |     (5, 6, get_number());
-   |     ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:60:5
    |
 LL |     box get_number();
-   |     ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:61:5
    |
 LL |     get_number()..;
-   |     ^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:62:5
    |
 LL |     ..get_number();
-   |     ^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:63:5
    |
 LL |     5..get_number();
-   |     ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();`
+   |     ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:64:5
    |
 LL |     [42, get_number()];
-   |     ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:65:5
    |
 LL |     [42, 55][get_usize()];
-   |     ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_usize();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:66:5
    |
 LL |     (42, get_number()).1;
-   |     ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:67:5
    |
 LL |     [get_number(); 55];
-   |     ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:68:5
    |
 LL |     [42; 55][get_usize()];
-   |     ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_usize();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:69:5
    |
 LL | /     {
 LL | |         get_number()
 LL | |     };
-   | |______^ help: replace it with: `get_number();`
+   | |______^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:72:5
    |
 LL | /     FooString {
 LL | |         s: String::from("blah"),
 LL | |     };
-   | |______^ help: replace it with: `String::from("blah");`
+   | |______^ help: statement can be reduced to: `String::from("blah");`
 
 error: aborting due to 20 previous errors