about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorflip1995 <philipp.krones@embecosm.com>2021-04-08 17:18:19 +0200
committerflip1995 <philipp.krones@embecosm.com>2021-04-08 17:36:41 +0200
commitffa2b7da2942a4dd27375a339582d78b7bb154e7 (patch)
tree69c13cbb6464322e4ed4e7ba09de08edcac85e01 /tests
parentcde58f7174cd83752b3c0a00a970dcc07c511077 (diff)
parentdb6ea84f8790e9e8488ee917ab72af28a4eccf61 (diff)
downloadrust-ffa2b7da2942a4dd27375a339582d78b7bb154e7.tar.gz
rust-ffa2b7da2942a4dd27375a339582d78b7bb154e7.zip
Merge remote-tracking branch 'upstream/master' into rustup
Diffstat (limited to 'tests')
-rw-r--r--tests/compile-test.rs16
-rw-r--r--tests/lint_message_convention.rs4
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr6
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr6
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr6
-rw-r--r--tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml1
-rw-r--r--tests/ui-internal/if_chain_style.rs92
-rw-r--r--tests/ui-internal/if_chain_style.stderr85
-rw-r--r--tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs16
-rw-r--r--tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr14
-rw-r--r--tests/ui/borrow_interior_mutable_const/others.rs6
-rw-r--r--tests/ui/borrow_interior_mutable_const/others.stderr28
-rw-r--r--tests/ui/branches_sharing_code/shared_at_bottom.rs209
-rw-r--r--tests/ui/branches_sharing_code/shared_at_bottom.stderr143
-rw-r--r--tests/ui/branches_sharing_code/shared_at_top.rs103
-rw-r--r--tests/ui/branches_sharing_code/shared_at_top.stderr121
-rw-r--r--tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs119
-rw-r--r--tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr154
-rw-r--r--tests/ui/branches_sharing_code/valid_if_blocks.rs155
-rw-r--r--tests/ui/branches_sharing_code/valid_if_blocks.stderr101
-rw-r--r--tests/ui/checked_unwrap/complex_conditionals.rs2
-rw-r--r--tests/ui/checked_unwrap/complex_conditionals_nested.rs2
-rw-r--r--tests/ui/checked_unwrap/simple_conditionals.rs2
-rw-r--r--tests/ui/clone_on_copy.fixed34
-rw-r--r--tests/ui/clone_on_copy.rs34
-rw-r--r--tests/ui/clone_on_copy.stderr30
-rw-r--r--tests/ui/clone_on_copy_mut.rs18
-rw-r--r--tests/ui/collapsible_match2.rs7
-rw-r--r--tests/ui/collapsible_match2.stderr20
-rw-r--r--tests/ui/crashes/ice-7012.rs17
-rw-r--r--tests/ui/default_numeric_fallback.rs1
-rw-r--r--tests/ui/default_numeric_fallback.stderr48
-rw-r--r--tests/ui/derive.rs21
-rw-r--r--tests/ui/derive.stderr30
-rw-r--r--tests/ui/doc.rs21
-rw-r--r--tests/ui/escape_analysis.rs4
-rw-r--r--tests/ui/floating_point_log.fixed2
-rw-r--r--tests/ui/floating_point_log.stderr2
-rw-r--r--tests/ui/from_str_radix_10.stderr2
-rw-r--r--tests/ui/if_same_then_else.rs3
-rw-r--r--tests/ui/if_same_then_else.stderr88
-rw-r--r--tests/ui/if_same_then_else2.rs3
-rw-r--r--tests/ui/if_same_then_else2.stderr106
-rw-r--r--tests/ui/implicit_clone.rs2
-rw-r--r--tests/ui/into_iter_on_ref.fixed2
-rw-r--r--tests/ui/into_iter_on_ref.rs2
-rw-r--r--tests/ui/len_without_is_empty.rs99
-rw-r--r--tests/ui/len_without_is_empty.stderr79
-rw-r--r--tests/ui/let_if_seq.rs3
-rw-r--r--tests/ui/let_if_seq.stderr8
-rw-r--r--tests/ui/linkedlist.rs (renamed from tests/ui/dlist.rs)3
-rw-r--r--tests/ui/linkedlist.stderr (renamed from tests/ui/dlist.stderr)32
-rw-r--r--tests/ui/manual_map_option.fixed15
-rw-r--r--tests/ui/manual_map_option.rs17
-rw-r--r--tests/ui/manual_map_option.stderr55
-rw-r--r--tests/ui/manual_memcpy/with_loop_counters.stderr2
-rw-r--r--tests/ui/match_ref_pats.stderr16
-rw-r--r--tests/ui/match_wildcard_for_single_variants.fixed16
-rw-r--r--tests/ui/match_wildcard_for_single_variants.rs16
-rw-r--r--tests/ui/min_rust_version_attr.rs6
-rw-r--r--tests/ui/min_rust_version_attr.stderr8
-rw-r--r--tests/ui/missing_panics_doc.rs (renamed from tests/ui/doc_panics.rs)40
-rw-r--r--tests/ui/missing_panics_doc.stderr (renamed from tests/ui/doc_panics.stderr)54
-rw-r--r--tests/ui/needless_bool/simple.rs3
-rw-r--r--tests/ui/needless_bool/simple.stderr8
-rw-r--r--tests/ui/needless_collect_indirect.stderr45
-rw-r--r--tests/ui/needless_for_each_fixable.fixed113
-rw-r--r--tests/ui/needless_for_each_fixable.rs113
-rw-r--r--tests/ui/needless_for_each_fixable.stderr123
-rw-r--r--tests/ui/needless_for_each_unfixable.rs14
-rw-r--r--tests/ui/needless_for_each_unfixable.stderr29
-rw-r--r--tests/ui/needless_return.fixed9
-rw-r--r--tests/ui/needless_return.rs9
-rw-r--r--tests/ui/needless_return.stderr36
-rw-r--r--tests/ui/non_octal_unix_permissions.fixed33
-rw-r--r--tests/ui/non_octal_unix_permissions.rs33
-rw-r--r--tests/ui/non_octal_unix_permissions.stderr28
-rw-r--r--tests/ui/option_filter_map.fixed23
-rw-r--r--tests/ui/option_filter_map.rs25
-rw-r--r--tests/ui/option_filter_map.stderr56
-rw-r--r--tests/ui/option_option.rs3
-rw-r--r--tests/ui/option_option.stderr38
-rw-r--r--tests/ui/redundant_clone.fixed24
-rw-r--r--tests/ui/redundant_clone.rs24
-rw-r--r--tests/ui/redundant_clone.stderr20
-rw-r--r--tests/ui/redundant_slicing.rs29
-rw-r--r--tests/ui/redundant_slicing.stderr32
-rw-r--r--tests/ui/ref_option_ref.rs2
-rw-r--r--tests/ui/ref_option_ref.stderr2
-rw-r--r--tests/ui/result_unit_error.stderr20
-rw-r--r--tests/ui/same_item_push.rs7
-rw-r--r--tests/ui/stable_sort_primitive.fixed2
-rw-r--r--tests/ui/stable_sort_primitive.rs2
-rw-r--r--tests/ui/temporary_assignment.rs1
-rw-r--r--tests/ui/temporary_assignment.stderr8
-rw-r--r--tests/ui/type_complexity.rs (renamed from tests/ui/complex_types.rs)0
-rw-r--r--tests/ui/type_complexity.stderr (renamed from tests/ui/complex_types.stderr)30
-rw-r--r--tests/ui/upper_case_acronyms.rs14
-rw-r--r--tests/ui/upper_case_acronyms.stderr8
-rw-r--r--tests/ui/vec.fixed16
-rw-r--r--tests/ui/vec.rs16
-rw-r--r--tests/ui/vec.stderr44
-rw-r--r--tests/ui/vec_box_sized.fixed2
-rw-r--r--tests/ui/vec_box_sized.rs2
-rw-r--r--tests/ui/vec_box_sized.stderr26
-rw-r--r--tests/ui/wrong_self_convention.rs9
-rw-r--r--tests/ui/wrong_self_convention.stderr4
-rw-r--r--tests/ui/wrong_self_convention2.rs32
-rw-r--r--tests/ui/wrong_self_convention2.stderr11
109 files changed, 3058 insertions, 427 deletions
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index 0594663786c..f4d354f0bf9 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -98,7 +98,7 @@ fn default_config() -> compiletest::Config {
 fn run_mode(cfg: &mut compiletest::Config) {
     cfg.mode = TestMode::Ui;
     cfg.src_base = Path::new("tests").join("ui");
-    compiletest::run_tests(&cfg);
+    compiletest::run_tests(cfg);
 }
 
 fn run_internal_tests(cfg: &mut compiletest::Config) {
@@ -108,7 +108,7 @@ fn run_internal_tests(cfg: &mut compiletest::Config) {
     }
     cfg.mode = TestMode::Ui;
     cfg.src_base = Path::new("tests").join("ui-internal");
-    compiletest::run_tests(&cfg);
+    compiletest::run_tests(cfg);
 }
 
 fn run_ui_toml(config: &mut compiletest::Config) {
@@ -136,7 +136,7 @@ fn run_ui_toml(config: &mut compiletest::Config) {
                     base: config.src_base.clone(),
                     relative_dir: dir_path.file_name().unwrap().into(),
                 };
-                let test_name = compiletest::make_test_name(&config, &paths);
+                let test_name = compiletest::make_test_name(config, &paths);
                 let index = tests
                     .iter()
                     .position(|test| test.desc.name == test_name)
@@ -150,10 +150,10 @@ fn run_ui_toml(config: &mut compiletest::Config) {
     config.mode = TestMode::Ui;
     config.src_base = Path::new("tests").join("ui-toml").canonicalize().unwrap();
 
-    let tests = compiletest::make_tests(&config);
+    let tests = compiletest::make_tests(config);
 
     let manifest_dir = var("CARGO_MANIFEST_DIR").unwrap_or_default();
-    let res = run_tests(&config, tests);
+    let res = run_tests(config, tests);
     set_var("CARGO_MANIFEST_DIR", &manifest_dir);
     match res {
         Ok(true) => {},
@@ -221,7 +221,7 @@ fn run_ui_cargo(config: &mut compiletest::Config) {
                         base: config.src_base.clone(),
                         relative_dir: src_path.strip_prefix(&config.src_base).unwrap().into(),
                     };
-                    let test_name = compiletest::make_test_name(&config, &paths);
+                    let test_name = compiletest::make_test_name(config, &paths);
                     let index = tests
                         .iter()
                         .position(|test| test.desc.name == test_name)
@@ -240,11 +240,11 @@ fn run_ui_cargo(config: &mut compiletest::Config) {
     config.mode = TestMode::Ui;
     config.src_base = Path::new("tests").join("ui-cargo").canonicalize().unwrap();
 
-    let tests = compiletest::make_tests(&config);
+    let tests = compiletest::make_tests(config);
 
     let current_dir = env::current_dir().unwrap();
     let conf_dir = var("CLIPPY_CONF_DIR").unwrap_or_default();
-    let res = run_tests(&config, &config.filters, tests);
+    let res = run_tests(config, &config.filters, tests);
     env::set_current_dir(current_dir).unwrap();
     set_var("CLIPPY_CONF_DIR", conf_dir);
 
diff --git a/tests/lint_message_convention.rs b/tests/lint_message_convention.rs
index 3f754c255b7..2f8989c8e11 100644
--- a/tests/lint_message_convention.rs
+++ b/tests/lint_message_convention.rs
@@ -89,14 +89,14 @@ fn lint_message_convention() {
         .filter(|message| !message.bad_lines.is_empty())
         .collect();
 
-    bad_tests.iter().for_each(|message| {
+    for message in &bad_tests {
         eprintln!(
             "error: the test '{}' contained the following nonconforming lines :",
             message.path.display()
         );
         message.bad_lines.iter().for_each(|line| eprintln!("{}", line));
         eprintln!("\n\n");
-    });
+    }
 
     eprintln!(
         "\n\n\nLint message should not start with a capital letter and should not have punctuation at the end of the message unless multiple sentences are needed."
diff --git a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr
index c8ae6c820df..5e9aa8dc36a 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr
@@ -1,9 +1,7 @@
-error: package `cargo_common_metadata` is missing `package.authors` metadata
+error: package `cargo_common_metadata` is missing `package.description` metadata
    |
    = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
-error: package `cargo_common_metadata` is missing `package.description` metadata
-
 error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata
 
 error: package `cargo_common_metadata` is missing `package.repository` metadata
@@ -14,5 +12,5 @@ error: package `cargo_common_metadata` is missing `package.keywords` metadata
 
 error: package `cargo_common_metadata` is missing `package.categories` metadata
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr
index c8ae6c820df..5e9aa8dc36a 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr
@@ -1,9 +1,7 @@
-error: package `cargo_common_metadata` is missing `package.authors` metadata
+error: package `cargo_common_metadata` is missing `package.description` metadata
    |
    = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
-error: package `cargo_common_metadata` is missing `package.description` metadata
-
 error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata
 
 error: package `cargo_common_metadata` is missing `package.repository` metadata
@@ -14,5 +12,5 @@ error: package `cargo_common_metadata` is missing `package.keywords` metadata
 
 error: package `cargo_common_metadata` is missing `package.categories` metadata
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr
index c8ae6c820df..5e9aa8dc36a 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr
@@ -1,9 +1,7 @@
-error: package `cargo_common_metadata` is missing `package.authors` metadata
+error: package `cargo_common_metadata` is missing `package.description` metadata
    |
    = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
-error: package `cargo_common_metadata` is missing `package.description` metadata
-
 error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata
 
 error: package `cargo_common_metadata` is missing `package.repository` metadata
@@ -14,5 +12,5 @@ error: package `cargo_common_metadata` is missing `package.keywords` metadata
 
 error: package `cargo_common_metadata` is missing `package.categories` metadata
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml
index 737e84e963c..cb4774d43a2 100644
--- a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml
+++ b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml
@@ -2,7 +2,6 @@
 name = "cargo_common_metadata"
 version = "0.1.0"
 publish = false
-authors = ["Random person from the Internet <someone@someplace.org>"]
 description = "A test package for the cargo_common_metadata lint"
 repository = "https://github.com/someone/cargo_common_metadata"
 readme = "README.md"
diff --git a/tests/ui-internal/if_chain_style.rs b/tests/ui-internal/if_chain_style.rs
new file mode 100644
index 00000000000..8e871707aa8
--- /dev/null
+++ b/tests/ui-internal/if_chain_style.rs
@@ -0,0 +1,92 @@
+#![warn(clippy::if_chain_style)]
+#![allow(clippy::no_effect)]
+
+extern crate if_chain;
+
+use if_chain::if_chain;
+
+fn main() {
+    if true {
+        let x = "";
+        // `if_chain!` inside `if`
+        if_chain! {
+            if true;
+            if true;
+            then {}
+        }
+    }
+    if_chain! {
+        if true
+            // multi-line AND'ed conditions
+            && false;
+        if let Some(1) = Some(1);
+        // `let` before `then`
+        let x = "";
+        then {
+            ();
+        }
+    }
+    if_chain! {
+        // single `if` condition
+        if true;
+        then {
+            let x = "";
+            // nested if
+            if true {}
+        }
+    }
+    if_chain! {
+        // starts with `let ..`
+        let x = "";
+        if let Some(1) = Some(1);
+        then {
+            let x = "";
+            let x = "";
+            // nested if_chain!
+            if_chain! {
+                if true;
+                if true;
+                then {}
+            }
+        }
+    }
+}
+
+fn negative() {
+    if true {
+        ();
+        if_chain! {
+            if true;
+            if true;
+            then { (); }
+        }
+    }
+    if_chain! {
+        if true;
+        let x = "";
+        if true;
+        then { (); }
+    }
+    if_chain! {
+        if true;
+        if true;
+        then {
+            if true { 1 } else { 2 }
+        } else {
+            3
+        }
+    };
+    if true {
+        if_chain! {
+            if true;
+            if true;
+            then {}
+        }
+    } else if false {
+        if_chain! {
+            if true;
+            if false;
+            then {}
+        }
+    }
+}
diff --git a/tests/ui-internal/if_chain_style.stderr b/tests/ui-internal/if_chain_style.stderr
new file mode 100644
index 00000000000..b53c3ea05da
--- /dev/null
+++ b/tests/ui-internal/if_chain_style.stderr
@@ -0,0 +1,85 @@
+error: this `if` can be part of the inner `if_chain!`
+  --> $DIR/if_chain_style.rs:9:5
+   |
+LL | /     if true {
+LL | |         let x = "";
+LL | |         // `if_chain!` inside `if`
+LL | |         if_chain! {
+...  |
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::if-chain-style` implied by `-D warnings`
+help: this `let` statement can also be in the `if_chain!`
+  --> $DIR/if_chain_style.rs:10:9
+   |
+LL |         let x = "";
+   |         ^^^^^^^^^^^
+
+error: `if a && b;` should be `if a; if b;`
+  --> $DIR/if_chain_style.rs:19:12
+   |
+LL |           if true
+   |  ____________^
+LL | |             // multi-line AND'ed conditions
+LL | |             && false;
+   | |____________________^
+
+error: `let` expression should be inside `then { .. }`
+  --> $DIR/if_chain_style.rs:24:9
+   |
+LL |         let x = "";
+   |         ^^^^^^^^^^^
+
+error: this `if` can be part of the outer `if_chain!`
+  --> $DIR/if_chain_style.rs:35:13
+   |
+LL |             if true {}
+   |             ^^^^^^^^^^
+   |
+help: this `let` statement can also be in the `if_chain!`
+  --> $DIR/if_chain_style.rs:33:13
+   |
+LL |             let x = "";
+   |             ^^^^^^^^^^^
+
+error: `if_chain!` only has one `if`
+  --> $DIR/if_chain_style.rs:29:5
+   |
+LL | /     if_chain! {
+LL | |         // single `if` condition
+LL | |         if true;
+LL | |         then {
+...  |
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `let` expression should be above the `if_chain!`
+  --> $DIR/if_chain_style.rs:40:9
+   |
+LL |         let x = "";
+   |         ^^^^^^^^^^^
+
+error: this `if_chain!` can be merged with the outer `if_chain!`
+  --> $DIR/if_chain_style.rs:46:13
+   |
+LL | /             if_chain! {
+LL | |                 if true;
+LL | |                 if true;
+LL | |                 then {}
+LL | |             }
+   | |_____________^
+   |
+help: these `let` statements can also be in the `if_chain!`
+  --> $DIR/if_chain_style.rs:43:13
+   |
+LL | /             let x = "";
+LL | |             let x = "";
+   | |_______________________^
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs
index c6659edacc3..1a5cf1b1947 100644
--- a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs
+++ b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs
@@ -25,4 +25,20 @@ pub struct MIXEDCapital;
 
 pub struct FULLCAPITAL;
 
+// enum variants should not be linted if the num is pub
+pub enum ParseError<T> {
+    FULLCAPITAL(u8),
+    MIXEDCapital(String),
+    Utf8(std::string::FromUtf8Error),
+    Parse(T, String),
+}
+
+// private, do lint here
+enum ParseErrorPrivate<T> {
+    WASD(u8),
+    WASDMixed(String),
+    Utf8(std::string::FromUtf8Error),
+    Parse(T, String),
+}
+
 fn main() {}
diff --git a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr
index 38e30683d57..02f29bbefe1 100644
--- a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr
+++ b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr
@@ -66,5 +66,17 @@ error: name `GCCLLVMSomething` contains a capitalized acronym
 LL | struct GCCLLVMSomething;
    |        ^^^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `GccllvmSomething`
 
-error: aborting due to 11 previous errors
+error: name `WASD` contains a capitalized acronym
+  --> $DIR/upper_case_acronyms.rs:38:5
+   |
+LL |     WASD(u8),
+   |     ^^^^ help: consider making the acronym lowercase, except the initial letter: `Wasd`
+
+error: name `WASDMixed` contains a capitalized acronym
+  --> $DIR/upper_case_acronyms.rs:39:5
+   |
+LL |     WASDMixed(String),
+   |     ^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `WasdMixed`
+
+error: aborting due to 13 previous errors
 
diff --git a/tests/ui/borrow_interior_mutable_const/others.rs b/tests/ui/borrow_interior_mutable_const/others.rs
index ea25729d11d..4327f12c37c 100644
--- a/tests/ui/borrow_interior_mutable_const/others.rs
+++ b/tests/ui/borrow_interior_mutable_const/others.rs
@@ -1,5 +1,9 @@
 #![warn(clippy::borrow_interior_mutable_const)]
-#![allow(clippy::declare_interior_mutable_const, clippy::ref_in_deref)]
+#![allow(
+    clippy::declare_interior_mutable_const,
+    clippy::ref_in_deref,
+    clippy::needless_borrow
+)]
 #![allow(const_item_mutation)]
 
 use std::borrow::Cow;
diff --git a/tests/ui/borrow_interior_mutable_const/others.stderr b/tests/ui/borrow_interior_mutable_const/others.stderr
index 9a908cf30e9..f146b97cf61 100644
--- a/tests/ui/borrow_interior_mutable_const/others.stderr
+++ b/tests/ui/borrow_interior_mutable_const/others.stderr
@@ -1,5 +1,5 @@
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:54:5
+  --> $DIR/others.rs:58:5
    |
 LL |     ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
    |     ^^^^^^
@@ -8,7 +8,7 @@ LL |     ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:55:16
+  --> $DIR/others.rs:59:16
    |
 LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
    |                ^^^^^^
@@ -16,7 +16,7 @@ LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:58:22
+  --> $DIR/others.rs:62:22
    |
 LL |     let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
    |                      ^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:59:25
+  --> $DIR/others.rs:63:25
    |
 LL |     let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
    |                         ^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:60:27
+  --> $DIR/others.rs:64:27
    |
 LL |     let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
    |                           ^^^^^^^^^
@@ -40,7 +40,7 @@ LL |     let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:61:26
+  --> $DIR/others.rs:65:26
    |
 LL |     let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
    |                          ^^^^^^^^^
@@ -48,7 +48,7 @@ LL |     let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:72:14
+  --> $DIR/others.rs:76:14
    |
 LL |     let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
    |              ^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:73:14
+  --> $DIR/others.rs:77:14
    |
 LL |     let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
    |              ^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:74:19
+  --> $DIR/others.rs:78:19
    |
 LL |     let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
    |                   ^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL |     let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:75:14
+  --> $DIR/others.rs:79:14
    |
 LL |     let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
    |              ^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:76:13
+  --> $DIR/others.rs:80:13
    |
 LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
    |             ^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:82:13
+  --> $DIR/others.rs:86:13
    |
 LL |     let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
    |             ^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL |     let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:87:5
+  --> $DIR/others.rs:91:5
    |
 LL |     CELL.set(2); //~ ERROR interior mutability
    |     ^^^^
@@ -104,7 +104,7 @@ LL |     CELL.set(2); //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:88:16
+  --> $DIR/others.rs:92:16
    |
 LL |     assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
    |                ^^^^
diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.rs b/tests/ui/branches_sharing_code/shared_at_bottom.rs
new file mode 100644
index 00000000000..c389c243d44
--- /dev/null
+++ b/tests/ui/branches_sharing_code/shared_at_bottom.rs
@@ -0,0 +1,209 @@
+#![allow(dead_code)]
+#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+
+// This tests the branches_sharing_code lint at the end of blocks
+
+fn simple_examples() {
+    let x = 1;
+
+    let _ = if x == 7 {
+        println!("Branch I");
+        let start_value = 0;
+        println!("=^.^=");
+
+        // Same but not moveable due to `start_value`
+        let _ = start_value;
+
+        // The rest is self contained and moveable => Only lint the rest
+        let result = false;
+        println!("Block end!");
+        result
+    } else {
+        println!("Branch II");
+        let start_value = 8;
+        println!("xD");
+
+        // Same but not moveable due to `start_value`
+        let _ = start_value;
+
+        // The rest is self contained and moveable => Only lint the rest
+        let result = false;
+        println!("Block end!");
+        result
+    };
+
+    // Else if block
+    if x == 9 {
+        println!("The index is: 6");
+
+        println!("Same end of block");
+    } else if x == 8 {
+        println!("The index is: 4");
+
+        // We should only get a lint trigger for the last statement
+        println!("This is also eq with the else block");
+        println!("Same end of block");
+    } else {
+        println!("This is also eq with the else block");
+        println!("Same end of block");
+    }
+
+    // Use of outer scope value
+    let outer_scope_value = "I'm outside the if block";
+    if x < 99 {
+        let z = "How are you";
+        println!("I'm a local because I use the value `z`: `{}`", z);
+
+        println!(
+            "I'm moveable because I know: `outer_scope_value`: '{}'",
+            outer_scope_value
+        );
+    } else {
+        let z = 45678000;
+        println!("I'm a local because I use the value `z`: `{}`", z);
+
+        println!(
+            "I'm moveable because I know: `outer_scope_value`: '{}'",
+            outer_scope_value
+        );
+    }
+
+    if x == 9 {
+        if x == 8 {
+            // No parent!!
+            println!("---");
+            println!("Hello World");
+        } else {
+            println!("Hello World");
+        }
+    }
+}
+
+/// Simple examples where the move can cause some problems due to moved values
+fn simple_but_suggestion_is_invalid() {
+    let x = 16;
+
+    // Local value
+    let later_used_value = 17;
+    if x == 9 {
+        let _ = 9;
+        let later_used_value = "A string value";
+        println!("{}", later_used_value);
+    } else {
+        let later_used_value = "A string value";
+        println!("{}", later_used_value);
+        // I'm expecting a note about this
+    }
+    println!("{}", later_used_value);
+
+    // outer function
+    if x == 78 {
+        let simple_examples = "I now identify as a &str :)";
+        println!("This is the new simple_example: {}", simple_examples);
+    } else {
+        println!("Separator print statement");
+
+        let simple_examples = "I now identify as a &str :)";
+        println!("This is the new simple_example: {}", simple_examples);
+    }
+    simple_examples();
+}
+
+/// Tests where the blocks are not linted due to the used value scope
+fn not_moveable_due_to_value_scope() {
+    let x = 18;
+
+    // Using a local value in the moved code
+    if x == 9 {
+        let y = 18;
+        println!("y is: `{}`", y);
+    } else {
+        let y = "A string";
+        println!("y is: `{}`", y);
+    }
+
+    // Using a local value in the expression
+    let _ = if x == 0 {
+        let mut result = x + 1;
+
+        println!("1. Doing some calculations");
+        println!("2. Some more calculations");
+        println!("3. Setting result");
+
+        result
+    } else {
+        let mut result = x - 1;
+
+        println!("1. Doing some calculations");
+        println!("2. Some more calculations");
+        println!("3. Setting result");
+
+        result
+    };
+
+    let _ = if x == 7 {
+        let z1 = 100;
+        println!("z1: {}", z1);
+
+        let z2 = z1;
+        println!("z2: {}", z2);
+
+        z2
+    } else {
+        let z1 = 300;
+        println!("z1: {}", z1);
+
+        let z2 = z1;
+        println!("z2: {}", z2);
+
+        z2
+    };
+}
+
+/// This should add a note to the lint msg since the moved expression is not `()`
+fn added_note_for_expression_use() -> u32 {
+    let x = 9;
+
+    let _ = if x == 7 {
+        x << 2
+    } else {
+        let _ = 6;
+        x << 2
+    };
+
+    if x == 9 {
+        x * 4
+    } else {
+        let _ = 17;
+        x * 4
+    }
+}
+
+#[rustfmt::skip]
+fn test_suggestion_with_weird_formatting() {
+    let x = 9;
+    let mut a = 0;
+    let mut b = 0;
+
+    // The error message still looks weird tbh but this is the best I can do
+    // for weird formatting
+    if x == 17 { b = 1; a = 0x99; } else { a = 0x99; }
+}
+
+fn fp_test() {
+    let x = 17;
+
+    if x == 18 {
+        let y = 19;
+        if y < x {
+            println!("Trigger")
+        }
+    } else {
+        let z = 166;
+        if z < x {
+            println!("Trigger")
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/tests/ui/branches_sharing_code/shared_at_bottom.stderr
new file mode 100644
index 00000000000..271fcd8b6c1
--- /dev/null
+++ b/tests/ui/branches_sharing_code/shared_at_bottom.stderr
@@ -0,0 +1,143 @@
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:30:5
+   |
+LL | /         let result = false;
+LL | |         println!("Block end!");
+LL | |         result
+LL | |     };
+   | |_____^
+   |
+note: the lint level is defined here
+  --> $DIR/shared_at_bottom.rs:2:36
+   |
+LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: The end suggestion probably needs some adjustments to use the expression result correctly
+help: consider moving the end statements out like this
+   |
+LL |     }
+LL |     let result = false;
+LL |     println!("Block end!");
+LL |     result;
+   |
+
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:48:5
+   |
+LL | /         println!("Same end of block");
+LL | |     }
+   | |_____^
+   |
+help: consider moving the end statements out like this
+   |
+LL |     }
+LL |     println!("Same end of block");
+   |
+
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:65:5
+   |
+LL | /         println!(
+LL | |             "I'm moveable because I know: `outer_scope_value`: '{}'",
+LL | |             outer_scope_value
+LL | |         );
+LL | |     }
+   | |_____^
+   |
+help: consider moving the end statements out like this
+   |
+LL |     }
+LL |     println!(
+LL |         "I'm moveable because I know: `outer_scope_value`: '{}'",
+LL |         outer_scope_value
+LL |     );
+   |
+
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:77:9
+   |
+LL | /             println!("Hello World");
+LL | |         }
+   | |_________^
+   |
+help: consider moving the end statements out like this
+   |
+LL |         }
+LL |         println!("Hello World");
+   |
+
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:93:5
+   |
+LL | /         let later_used_value = "A string value";
+LL | |         println!("{}", later_used_value);
+LL | |         // I'm expecting a note about this
+LL | |     }
+   | |_____^
+   |
+   = warning: Some moved values might need to be renamed to avoid wrong references
+help: consider moving the end statements out like this
+   |
+LL |     }
+LL |     let later_used_value = "A string value";
+LL |     println!("{}", later_used_value);
+   |
+
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:106:5
+   |
+LL | /         let simple_examples = "I now identify as a &str :)";
+LL | |         println!("This is the new simple_example: {}", simple_examples);
+LL | |     }
+   | |_____^
+   |
+   = warning: Some moved values might need to be renamed to avoid wrong references
+help: consider moving the end statements out like this
+   |
+LL |     }
+LL |     let simple_examples = "I now identify as a &str :)";
+LL |     println!("This is the new simple_example: {}", simple_examples);
+   |
+
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:171:5
+   |
+LL | /         x << 2
+LL | |     };
+   | |_____^
+   |
+   = note: The end suggestion probably needs some adjustments to use the expression result correctly
+help: consider moving the end statements out like this
+   |
+LL |     }
+LL |     x << 2;
+   |
+
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:178:5
+   |
+LL | /         x * 4
+LL | |     }
+   | |_____^
+   |
+   = note: The end suggestion probably needs some adjustments to use the expression result correctly
+help: consider moving the end statements out like this
+   |
+LL |     }
+LL |     x * 4
+   |
+
+error: all if blocks contain the same code at the end
+  --> $DIR/shared_at_bottom.rs:190:44
+   |
+LL |     if x == 17 { b = 1; a = 0x99; } else { a = 0x99; }
+   |                                            ^^^^^^^^^^^
+   |
+help: consider moving the end statements out like this
+   |
+LL |     if x == 17 { b = 1; a = 0x99; } else { }
+LL |     a = 0x99;
+   |
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/branches_sharing_code/shared_at_top.rs b/tests/ui/branches_sharing_code/shared_at_top.rs
new file mode 100644
index 00000000000..e65bcfd7873
--- /dev/null
+++ b/tests/ui/branches_sharing_code/shared_at_top.rs
@@ -0,0 +1,103 @@
+#![allow(dead_code, clippy::eval_order_dependence)]
+#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+
+// This tests the branches_sharing_code lint at the start of blocks
+
+fn simple_examples() {
+    let x = 0;
+
+    // Simple
+    if true {
+        println!("Hello World!");
+        println!("I'm branch nr: 1");
+    } else {
+        println!("Hello World!");
+        println!("I'm branch nr: 2");
+    }
+
+    // Else if
+    if x == 0 {
+        let y = 9;
+        println!("The value y was set to: `{}`", y);
+        let _z = y;
+
+        println!("I'm the true start index of arrays");
+    } else if x == 1 {
+        let y = 9;
+        println!("The value y was set to: `{}`", y);
+        let _z = y;
+
+        println!("I start counting from 1 so my array starts from `1`");
+    } else {
+        let y = 9;
+        println!("The value y was set to: `{}`", y);
+        let _z = y;
+
+        println!("Ha, Pascal allows you to start the array where you want")
+    }
+
+    // Return a value
+    let _ = if x == 7 {
+        let y = 16;
+        println!("What can I say except: \"you're welcome?\"");
+        let _ = y;
+        x
+    } else {
+        let y = 16;
+        println!("Thank you");
+        y
+    };
+}
+
+/// Simple examples where the move can cause some problems due to moved values
+fn simple_but_suggestion_is_invalid() {
+    let x = 10;
+
+    // Can't be automatically moved because used_value_name is getting used again
+    let used_value_name = 19;
+    if x == 10 {
+        let used_value_name = "Different type";
+        println!("Str: {}", used_value_name);
+        let _ = 1;
+    } else {
+        let used_value_name = "Different type";
+        println!("Str: {}", used_value_name);
+        let _ = 2;
+    }
+    let _ = used_value_name;
+
+    // This can be automatically moved as `can_be_overridden` is not used again
+    let can_be_overridden = 8;
+    let _ = can_be_overridden;
+    if x == 11 {
+        let can_be_overridden = "Move me";
+        println!("I'm also moveable");
+        let _ = 111;
+    } else {
+        let can_be_overridden = "Move me";
+        println!("I'm also moveable");
+        let _ = 222;
+    }
+}
+
+/// This function tests that the `IS_SAME_THAN_ELSE` only covers the lint if it's enabled.
+fn check_if_same_than_else_mask() {
+    let x = 2021;
+
+    #[allow(clippy::if_same_then_else)]
+    if x == 2020 {
+        println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint.");
+        println!("Because `IF_SAME_THEN_ELSE` is allowed here");
+    } else {
+        println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint.");
+        println!("Because `IF_SAME_THEN_ELSE` is allowed here");
+    }
+
+    if x == 2019 {
+        println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
+    } else {
+        println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/branches_sharing_code/shared_at_top.stderr b/tests/ui/branches_sharing_code/shared_at_top.stderr
new file mode 100644
index 00000000000..15867e9ea02
--- /dev/null
+++ b/tests/ui/branches_sharing_code/shared_at_top.stderr
@@ -0,0 +1,121 @@
+error: all if blocks contain the same code at the start
+  --> $DIR/shared_at_top.rs:10:5
+   |
+LL | /     if true {
+LL | |         println!("Hello World!");
+   | |_________________________________^
+   |
+note: the lint level is defined here
+  --> $DIR/shared_at_top.rs:2:36
+   |
+LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider moving the start statements out like this
+   |
+LL |     println!("Hello World!");
+LL |     if true {
+   |
+
+error: all if blocks contain the same code at the start
+  --> $DIR/shared_at_top.rs:19:5
+   |
+LL | /     if x == 0 {
+LL | |         let y = 9;
+LL | |         println!("The value y was set to: `{}`", y);
+LL | |         let _z = y;
+   | |___________________^
+   |
+   = warning: Some moved values might need to be renamed to avoid wrong references
+help: consider moving the start statements out like this
+   |
+LL |     let y = 9;
+LL |     println!("The value y was set to: `{}`", y);
+LL |     let _z = y;
+LL |     if x == 0 {
+   |
+
+error: all if blocks contain the same code at the start
+  --> $DIR/shared_at_top.rs:40:5
+   |
+LL | /     let _ = if x == 7 {
+LL | |         let y = 16;
+   | |___________________^
+   |
+help: consider moving the start statements out like this
+   |
+LL |     let y = 16;
+LL |     let _ = if x == 7 {
+   |
+
+error: all if blocks contain the same code at the start
+  --> $DIR/shared_at_top.rs:58:5
+   |
+LL | /     if x == 10 {
+LL | |         let used_value_name = "Different type";
+LL | |         println!("Str: {}", used_value_name);
+   | |_____________________________________________^
+   |
+   = warning: Some moved values might need to be renamed to avoid wrong references
+help: consider moving the start statements out like this
+   |
+LL |     let used_value_name = "Different type";
+LL |     println!("Str: {}", used_value_name);
+LL |     if x == 10 {
+   |
+
+error: all if blocks contain the same code at the start
+  --> $DIR/shared_at_top.rs:72:5
+   |
+LL | /     if x == 11 {
+LL | |         let can_be_overridden = "Move me";
+LL | |         println!("I'm also moveable");
+   | |______________________________________^
+   |
+   = warning: Some moved values might need to be renamed to avoid wrong references
+help: consider moving the start statements out like this
+   |
+LL |     let can_be_overridden = "Move me";
+LL |     println!("I'm also moveable");
+LL |     if x == 11 {
+   |
+
+error: all if blocks contain the same code at the start
+  --> $DIR/shared_at_top.rs:88:5
+   |
+LL | /     if x == 2020 {
+LL | |         println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint.");
+LL | |         println!("Because `IF_SAME_THEN_ELSE` is allowed here");
+   | |________________________________________________________________^
+   |
+help: consider moving the start statements out like this
+   |
+LL |     println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint.");
+LL |     println!("Because `IF_SAME_THEN_ELSE` is allowed here");
+LL |     if x == 2020 {
+   |
+
+error: this `if` has identical blocks
+  --> $DIR/shared_at_top.rs:96:18
+   |
+LL |       if x == 2019 {
+   |  __________________^
+LL | |         println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
+LL | |     } else {
+   | |_____^
+   |
+note: the lint level is defined here
+  --> $DIR/shared_at_top.rs:2:9
+   |
+LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: same as this
+  --> $DIR/shared_at_top.rs:98:12
+   |
+LL |       } else {
+   |  ____________^
+LL | |         println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
+LL | |     }
+   | |_____^
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
new file mode 100644
index 00000000000..deefdad32c9
--- /dev/null
+++ b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
@@ -0,0 +1,119 @@
+#![allow(dead_code)]
+#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+
+// branches_sharing_code at the top and bottom of the if blocks
+
+struct DataPack {
+    id: u32,
+    name: String,
+    some_data: Vec<u8>,
+}
+
+fn overlapping_eq_regions() {
+    let x = 9;
+
+    // Overlap with separator
+    if x == 7 {
+        let t = 7;
+        let _overlap_start = t * 2;
+        let _overlap_end = 2 * t;
+        let _u = 9;
+    } else {
+        let t = 7;
+        let _overlap_start = t * 2;
+        let _overlap_end = 2 * t;
+        println!("Overlap separator");
+        let _overlap_start = t * 2;
+        let _overlap_end = 2 * t;
+        let _u = 9;
+    }
+
+    // Overlap with separator
+    if x == 99 {
+        let r = 7;
+        let _overlap_start = r;
+        let _overlap_middle = r * r;
+        let _overlap_end = r * r * r;
+        let z = "end";
+    } else {
+        let r = 7;
+        let _overlap_start = r;
+        let _overlap_middle = r * r;
+        let _overlap_middle = r * r;
+        let _overlap_end = r * r * r;
+        let z = "end";
+    }
+}
+
+fn complexer_example() {
+    fn gen_id(x: u32, y: u32) -> u32 {
+        let x = x & 0x0000_ffff;
+        let y = (y & 0xffff_0000) << 16;
+        x | y
+    }
+
+    fn process_data(data: DataPack) {
+        let _ = data;
+    }
+
+    let x = 8;
+    let y = 9;
+    if (x > 7 && y < 13) || (x + y) % 2 == 1 {
+        let a = 0xcafe;
+        let b = 0xffff00ff;
+        let e_id = gen_id(a, b);
+
+        println!("From the a `{}` to the b `{}`", a, b);
+
+        let pack = DataPack {
+            id: e_id,
+            name: "Player 1".to_string(),
+            some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90],
+        };
+        process_data(pack);
+    } else {
+        let a = 0xcafe;
+        let b = 0xffff00ff;
+        let e_id = gen_id(a, b);
+
+        println!("The new ID is '{}'", e_id);
+
+        let pack = DataPack {
+            id: e_id,
+            name: "Player 1".to_string(),
+            some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90],
+        };
+        process_data(pack);
+    }
+}
+
+/// This should add a note to the lint msg since the moved expression is not `()`
+fn added_note_for_expression_use() -> u32 {
+    let x = 9;
+
+    let _ = if x == 7 {
+        let _ = 19;
+
+        let _splitter = 6;
+
+        x << 2
+    } else {
+        let _ = 19;
+
+        x << 2
+    };
+
+    if x == 9 {
+        let _ = 17;
+
+        let _splitter = 6;
+
+        x * 4
+    } else {
+        let _ = 17;
+
+        x * 4
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
new file mode 100644
index 00000000000..212cfb2f1d1
--- /dev/null
+++ b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
@@ -0,0 +1,154 @@
+error: all if blocks contain the same code at the start and the end. Here at the start
+  --> $DIR/shared_at_top_and_bottom.rs:16:5
+   |
+LL | /     if x == 7 {
+LL | |         let t = 7;
+LL | |         let _overlap_start = t * 2;
+LL | |         let _overlap_end = 2 * t;
+   | |_________________________________^
+   |
+note: the lint level is defined here
+  --> $DIR/shared_at_top_and_bottom.rs:2:36
+   |
+LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: and here at the end
+  --> $DIR/shared_at_top_and_bottom.rs:28:5
+   |
+LL | /         let _u = 9;
+LL | |     }
+   | |_____^
+help: consider moving the start statements out like this
+   |
+LL |     let t = 7;
+LL |     let _overlap_start = t * 2;
+LL |     let _overlap_end = 2 * t;
+LL |     if x == 7 {
+   |
+help: and consider moving the end statements out like this
+   |
+LL |     }
+LL |     let _u = 9;
+   |
+
+error: all if blocks contain the same code at the start and the end. Here at the start
+  --> $DIR/shared_at_top_and_bottom.rs:32:5
+   |
+LL | /     if x == 99 {
+LL | |         let r = 7;
+LL | |         let _overlap_start = r;
+LL | |         let _overlap_middle = r * r;
+   | |____________________________________^
+   |
+note: and here at the end
+  --> $DIR/shared_at_top_and_bottom.rs:43:5
+   |
+LL | /         let _overlap_end = r * r * r;
+LL | |         let z = "end";
+LL | |     }
+   | |_____^
+   = warning: Some moved values might need to be renamed to avoid wrong references
+help: consider moving the start statements out like this
+   |
+LL |     let r = 7;
+LL |     let _overlap_start = r;
+LL |     let _overlap_middle = r * r;
+LL |     if x == 99 {
+   |
+help: and consider moving the end statements out like this
+   |
+LL |     }
+LL |     let _overlap_end = r * r * r;
+LL |     let z = "end";
+   |
+
+error: all if blocks contain the same code at the start and the end. Here at the start
+  --> $DIR/shared_at_top_and_bottom.rs:61:5
+   |
+LL | /     if (x > 7 && y < 13) || (x + y) % 2 == 1 {
+LL | |         let a = 0xcafe;
+LL | |         let b = 0xffff00ff;
+LL | |         let e_id = gen_id(a, b);
+   | |________________________________^
+   |
+note: and here at the end
+  --> $DIR/shared_at_top_and_bottom.rs:81:5
+   |
+LL | /         let pack = DataPack {
+LL | |             id: e_id,
+LL | |             name: "Player 1".to_string(),
+LL | |             some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90],
+LL | |         };
+LL | |         process_data(pack);
+LL | |     }
+   | |_____^
+   = warning: Some moved values might need to be renamed to avoid wrong references
+help: consider moving the start statements out like this
+   |
+LL |     let a = 0xcafe;
+LL |     let b = 0xffff00ff;
+LL |     let e_id = gen_id(a, b);
+LL |     if (x > 7 && y < 13) || (x + y) % 2 == 1 {
+   |
+help: and consider moving the end statements out like this
+   |
+LL |     }
+LL |     let pack = DataPack {
+LL |         id: e_id,
+LL |         name: "Player 1".to_string(),
+LL |         some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90],
+LL |     };
+ ...
+
+error: all if blocks contain the same code at the start and the end. Here at the start
+  --> $DIR/shared_at_top_and_bottom.rs:94:5
+   |
+LL | /     let _ = if x == 7 {
+LL | |         let _ = 19;
+   | |___________________^
+   |
+note: and here at the end
+  --> $DIR/shared_at_top_and_bottom.rs:103:5
+   |
+LL | /         x << 2
+LL | |     };
+   | |_____^
+   = note: The end suggestion probably needs some adjustments to use the expression result correctly
+help: consider moving the start statements out like this
+   |
+LL |     let _ = 19;
+LL |     let _ = if x == 7 {
+   |
+help: and consider moving the end statements out like this
+   |
+LL |     }
+LL |     x << 2;
+   |
+
+error: all if blocks contain the same code at the start and the end. Here at the start
+  --> $DIR/shared_at_top_and_bottom.rs:106:5
+   |
+LL | /     if x == 9 {
+LL | |         let _ = 17;
+   | |___________________^
+   |
+note: and here at the end
+  --> $DIR/shared_at_top_and_bottom.rs:115:5
+   |
+LL | /         x * 4
+LL | |     }
+   | |_____^
+   = note: The end suggestion probably needs some adjustments to use the expression result correctly
+help: consider moving the start statements out like this
+   |
+LL |     let _ = 17;
+LL |     if x == 9 {
+   |
+help: and consider moving the end statements out like this
+   |
+LL |     }
+LL |     x * 4
+   |
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/branches_sharing_code/valid_if_blocks.rs b/tests/ui/branches_sharing_code/valid_if_blocks.rs
new file mode 100644
index 00000000000..0c70e3748ec
--- /dev/null
+++ b/tests/ui/branches_sharing_code/valid_if_blocks.rs
@@ -0,0 +1,155 @@
+#![allow(dead_code, clippy::eval_order_dependence)]
+#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+
+// This tests valid if blocks that shouldn't trigger the lint
+
+// Tests with value references are includes in "shared_code_at_bottom.rs"
+
+fn valid_examples() {
+    let x = 2;
+
+    // The edge statements are different
+    if x == 9 {
+        let y = 1 << 5;
+
+        println!("This is the same: vvv");
+        let _z = y;
+        println!("The block expression is different");
+
+        println!("Different end 1");
+    } else {
+        let y = 1 << 7;
+
+        println!("This is the same: vvv");
+        let _z = y;
+        println!("The block expression is different");
+
+        println!("Different end 2");
+    }
+
+    // No else
+    if x == 2 {
+        println!("Hello world!");
+        println!("Hello back, how are you?");
+
+        // This is different vvvv
+        println!("Howdy stranger =^.^=");
+
+        println!("Bye Bye World");
+    } else if x == 9 {
+        println!("Hello world!");
+        println!("Hello back, how are you?");
+
+        // This is different vvvv
+        println!("Hello reviewer :D");
+
+        println!("Bye Bye World");
+    }
+
+    // Overlapping statements only in else if blocks -> Don't lint
+    if x == 0 {
+        println!("I'm important!")
+    } else if x == 17 {
+        println!("I share code in else if");
+
+        println!("x is 17");
+    } else {
+        println!("I share code in else if");
+
+        println!("x is nether x nor 17");
+    }
+
+    // Mutability is different
+    if x == 13 {
+        let mut y = 9;
+        println!("Value y is: {}", y);
+        y += 16;
+        let _z1 = y;
+    } else {
+        let y = 9;
+        println!("Value y is: {}", y);
+        let _z2 = y;
+    }
+
+    // Same blocks but at start and bottom so no `if_same_then_else` lint
+    if x == 418 {
+        let y = 9;
+        let z = 8;
+        let _ = (x, y, z);
+        // Don't tell the programmer, my code is also in the else block
+    } else if x == 419 {
+        println!("+-----------+");
+        println!("|           |");
+        println!("|  O     O  |");
+        println!("|     °     |");
+        println!("|  \\_____/  |");
+        println!("|           |");
+        println!("+-----------+");
+    } else {
+        let y = 9;
+        let z = 8;
+        let _ = (x, y, z);
+        // I'm so much better than the x == 418 block. Trust me
+    }
+
+    let x = 1;
+    if true {
+        println!("{}", x);
+    } else {
+        let x = 2;
+        println!("{}", x);
+    }
+
+    // Let's test empty blocks
+    if false {
+    } else {
+    }
+}
+
+/// This makes sure that the `if_same_then_else` masks the `shared_code_in_if_blocks` lint
+fn trigger_other_lint() {
+    let x = 0;
+    let y = 1;
+
+    // Same block
+    if x == 0 {
+        let u = 19;
+        println!("How are u today?");
+        let _ = "This is a string";
+    } else {
+        let u = 19;
+        println!("How are u today?");
+        let _ = "This is a string";
+    }
+
+    // Only same expression
+    let _ = if x == 6 { 7 } else { 7 };
+
+    // Same in else if block
+    let _ = if x == 67 {
+        println!("Well I'm the most important block");
+        "I'm a pretty string"
+    } else if x == 68 {
+        println!("I'm a doppelgänger");
+        // Don't listen to my clone below
+
+        if y == 90 { "=^.^=" } else { ":D" }
+    } else {
+        // Don't listen to my clone above
+        println!("I'm a doppelgänger");
+
+        if y == 90 { "=^.^=" } else { ":D" }
+    };
+
+    if x == 0 {
+        println!("I'm single");
+    } else if x == 68 {
+        println!("I'm a doppelgänger");
+        // Don't listen to my clone below
+    } else {
+        // Don't listen to my clone above
+        println!("I'm a doppelgänger");
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/branches_sharing_code/valid_if_blocks.stderr b/tests/ui/branches_sharing_code/valid_if_blocks.stderr
new file mode 100644
index 00000000000..a815995e717
--- /dev/null
+++ b/tests/ui/branches_sharing_code/valid_if_blocks.stderr
@@ -0,0 +1,101 @@
+error: this `if` has identical blocks
+  --> $DIR/valid_if_blocks.rs:104:14
+   |
+LL |       if false {
+   |  ______________^
+LL | |     } else {
+   | |_____^
+   |
+note: the lint level is defined here
+  --> $DIR/valid_if_blocks.rs:2:9
+   |
+LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: same as this
+  --> $DIR/valid_if_blocks.rs:105:12
+   |
+LL |       } else {
+   |  ____________^
+LL | |     }
+   | |_____^
+
+error: this `if` has identical blocks
+  --> $DIR/valid_if_blocks.rs:115:15
+   |
+LL |       if x == 0 {
+   |  _______________^
+LL | |         let u = 19;
+LL | |         println!("How are u today?");
+LL | |         let _ = "This is a string";
+LL | |     } else {
+   | |_____^
+   |
+note: same as this
+  --> $DIR/valid_if_blocks.rs:119:12
+   |
+LL |       } else {
+   |  ____________^
+LL | |         let u = 19;
+LL | |         println!("How are u today?");
+LL | |         let _ = "This is a string";
+LL | |     }
+   | |_____^
+
+error: this `if` has identical blocks
+  --> $DIR/valid_if_blocks.rs:126:23
+   |
+LL |     let _ = if x == 6 { 7 } else { 7 };
+   |                       ^^^^^
+   |
+note: same as this
+  --> $DIR/valid_if_blocks.rs:126:34
+   |
+LL |     let _ = if x == 6 { 7 } else { 7 };
+   |                                  ^^^^^
+
+error: this `if` has identical blocks
+  --> $DIR/valid_if_blocks.rs:132:23
+   |
+LL |       } else if x == 68 {
+   |  _______________________^
+LL | |         println!("I'm a doppelgänger");
+LL | |         // Don't listen to my clone below
+LL | |
+LL | |         if y == 90 { "=^.^=" } else { ":D" }
+LL | |     } else {
+   | |_____^
+   |
+note: same as this
+  --> $DIR/valid_if_blocks.rs:137:12
+   |
+LL |       } else {
+   |  ____________^
+LL | |         // Don't listen to my clone above
+LL | |         println!("I'm a doppelgänger");
+LL | |
+LL | |         if y == 90 { "=^.^=" } else { ":D" }
+LL | |     };
+   | |_____^
+
+error: this `if` has identical blocks
+  --> $DIR/valid_if_blocks.rs:146:23
+   |
+LL |       } else if x == 68 {
+   |  _______________________^
+LL | |         println!("I'm a doppelgänger");
+LL | |         // Don't listen to my clone below
+LL | |     } else {
+   | |_____^
+   |
+note: same as this
+  --> $DIR/valid_if_blocks.rs:149:12
+   |
+LL |       } else {
+   |  ____________^
+LL | |         // Don't listen to my clone above
+LL | |         println!("I'm a doppelgänger");
+LL | |     }
+   | |_____^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/checked_unwrap/complex_conditionals.rs b/tests/ui/checked_unwrap/complex_conditionals.rs
index c986c992a07..ec082c73b44 100644
--- a/tests/ui/checked_unwrap/complex_conditionals.rs
+++ b/tests/ui/checked_unwrap/complex_conditionals.rs
@@ -1,5 +1,5 @@
 #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
-#![allow(clippy::if_same_then_else)]
+#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)]
 
 fn test_complex_conditions() {
     let x: Result<(), ()> = Ok(());
diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.rs b/tests/ui/checked_unwrap/complex_conditionals_nested.rs
index 2307996a48f..043ea4148dc 100644
--- a/tests/ui/checked_unwrap/complex_conditionals_nested.rs
+++ b/tests/ui/checked_unwrap/complex_conditionals_nested.rs
@@ -1,5 +1,5 @@
 #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
-#![allow(clippy::if_same_then_else)]
+#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)]
 
 fn test_nested() {
     fn nested() {
diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs
index 36967630834..8f23fb28827 100644
--- a/tests/ui/checked_unwrap/simple_conditionals.rs
+++ b/tests/ui/checked_unwrap/simple_conditionals.rs
@@ -1,5 +1,5 @@
 #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
-#![allow(clippy::if_same_then_else)]
+#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)]
 
 macro_rules! m {
     ($a:expr) => {
diff --git a/tests/ui/clone_on_copy.fixed b/tests/ui/clone_on_copy.fixed
index d924625132e..8d43f64768d 100644
--- a/tests/ui/clone_on_copy.fixed
+++ b/tests/ui/clone_on_copy.fixed
@@ -6,7 +6,8 @@
     clippy::deref_addrof,
     clippy::no_effect,
     clippy::unnecessary_operation,
-    clippy::vec_init_then_push
+    clippy::vec_init_then_push,
+    clippy::toplevel_ref_arg
 )]
 
 use std::cell::RefCell;
@@ -29,6 +30,37 @@ fn clone_on_copy() {
     let rc = RefCell::new(0);
     *rc.borrow();
 
+    let x = 0u32;
+    x.rotate_left(1);
+
+    #[derive(Clone, Copy)]
+    struct Foo;
+    impl Foo {
+        fn clone(&self) -> u32 {
+            0
+        }
+    }
+    Foo.clone(); // ok, this is not the clone trait
+
+    macro_rules! m {
+        ($e:expr) => {{ $e }};
+    }
+    m!(42);
+
+    struct Wrap([u32; 2]);
+    impl core::ops::Deref for Wrap {
+        type Target = [u32; 2];
+        fn deref(&self) -> &[u32; 2] {
+            &self.0
+        }
+    }
+    let x = Wrap([0, 0]);
+    (*x)[0];
+
+    let x = 42;
+    let ref y = x.clone(); // ok, binds by reference
+    let ref mut y = x.clone(); // ok, binds by reference
+
     // Issue #4348
     let mut x = 43;
     let _ = &x.clone(); // ok, getting a ref
diff --git a/tests/ui/clone_on_copy.rs b/tests/ui/clone_on_copy.rs
index 97f49467244..f15501f7184 100644
--- a/tests/ui/clone_on_copy.rs
+++ b/tests/ui/clone_on_copy.rs
@@ -6,7 +6,8 @@
     clippy::deref_addrof,
     clippy::no_effect,
     clippy::unnecessary_operation,
-    clippy::vec_init_then_push
+    clippy::vec_init_then_push,
+    clippy::toplevel_ref_arg
 )]
 
 use std::cell::RefCell;
@@ -29,6 +30,37 @@ fn clone_on_copy() {
     let rc = RefCell::new(0);
     rc.borrow().clone();
 
+    let x = 0u32;
+    x.clone().rotate_left(1);
+
+    #[derive(Clone, Copy)]
+    struct Foo;
+    impl Foo {
+        fn clone(&self) -> u32 {
+            0
+        }
+    }
+    Foo.clone(); // ok, this is not the clone trait
+
+    macro_rules! m {
+        ($e:expr) => {{ $e }};
+    }
+    m!(42).clone();
+
+    struct Wrap([u32; 2]);
+    impl core::ops::Deref for Wrap {
+        type Target = [u32; 2];
+        fn deref(&self) -> &[u32; 2] {
+            &self.0
+        }
+    }
+    let x = Wrap([0, 0]);
+    x.clone()[0];
+
+    let x = 42;
+    let ref y = x.clone(); // ok, binds by reference
+    let ref mut y = x.clone(); // ok, binds by reference
+
     // Issue #4348
     let mut x = 43;
     let _ = &x.clone(); // ok, getting a ref
diff --git a/tests/ui/clone_on_copy.stderr b/tests/ui/clone_on_copy.stderr
index 7a706884fb0..e7d28b4320b 100644
--- a/tests/ui/clone_on_copy.stderr
+++ b/tests/ui/clone_on_copy.stderr
@@ -1,5 +1,5 @@
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:23:5
+  --> $DIR/clone_on_copy.rs:24:5
    |
 LL |     42.clone();
    |     ^^^^^^^^^^ help: try removing the `clone` call: `42`
@@ -7,28 +7,46 @@ LL |     42.clone();
    = note: `-D clippy::clone-on-copy` implied by `-D warnings`
 
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:27:5
+  --> $DIR/clone_on_copy.rs:28:5
    |
 LL |     (&42).clone();
    |     ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)`
 
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:30:5
+  --> $DIR/clone_on_copy.rs:31:5
    |
 LL |     rc.borrow().clone();
    |     ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()`
 
+error: using `clone` on type `u32` which implements the `Copy` trait
+  --> $DIR/clone_on_copy.rs:34:5
+   |
+LL |     x.clone().rotate_left(1);
+   |     ^^^^^^^^^ help: try removing the `clone` call: `x`
+
+error: using `clone` on type `i32` which implements the `Copy` trait
+  --> $DIR/clone_on_copy.rs:48:5
+   |
+LL |     m!(42).clone();
+   |     ^^^^^^^^^^^^^^ help: try removing the `clone` call: `m!(42)`
+
+error: using `clone` on type `[u32; 2]` which implements the `Copy` trait
+  --> $DIR/clone_on_copy.rs:58:5
+   |
+LL |     x.clone()[0];
+   |     ^^^^^^^^^ help: try dereferencing it: `(*x)`
+
 error: using `clone` on type `char` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:36:14
+  --> $DIR/clone_on_copy.rs:68:14
    |
 LL |     is_ascii('z'.clone());
    |              ^^^^^^^^^^^ help: try removing the `clone` call: `'z'`
 
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:40:14
+  --> $DIR/clone_on_copy.rs:72:14
    |
 LL |     vec.push(42.clone());
    |              ^^^^^^^^^^ help: try removing the `clone` call: `42`
 
-error: aborting due to 5 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs
deleted file mode 100644
index 5bfa256623b..00000000000
--- a/tests/ui/clone_on_copy_mut.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-pub fn dec_read_dec(i: &mut i32) -> i32 {
-    *i -= 1;
-    let ret = *i;
-    *i -= 1;
-    ret
-}
-
-pub fn minus_1(i: &i32) -> i32 {
-    dec_read_dec(&mut i.clone())
-}
-
-fn main() {
-    let mut i = 10;
-    assert_eq!(minus_1(&i), 9);
-    assert_eq!(i, 10);
-    assert_eq!(dec_read_dec(&mut i), 9);
-    assert_eq!(i, 8);
-}
diff --git a/tests/ui/collapsible_match2.rs b/tests/ui/collapsible_match2.rs
index 8372a212477..542e6948427 100644
--- a/tests/ui/collapsible_match2.rs
+++ b/tests/ui/collapsible_match2.rs
@@ -1,5 +1,10 @@
 #![warn(clippy::collapsible_match)]
-#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)]
+#![allow(
+    clippy::needless_return,
+    clippy::no_effect,
+    clippy::single_match,
+    clippy::needless_borrow
+)]
 
 fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) {
     // if guards on outer match
diff --git a/tests/ui/collapsible_match2.stderr b/tests/ui/collapsible_match2.stderr
index c8a445ef369..ffef32d1fde 100644
--- a/tests/ui/collapsible_match2.stderr
+++ b/tests/ui/collapsible_match2.stderr
@@ -1,5 +1,5 @@
 error: unnecessary nested match
-  --> $DIR/collapsible_match2.rs:8:34
+  --> $DIR/collapsible_match2.rs:13:34
    |
 LL |               Ok(val) if make() => match val {
    |  __________________________________^
@@ -10,7 +10,7 @@ LL | |             },
    |
    = note: `-D clippy::collapsible-match` implied by `-D warnings`
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match2.rs:8:16
+  --> $DIR/collapsible_match2.rs:13:16
    |
 LL |             Ok(val) if make() => match val {
    |                ^^^ replace this binding
@@ -18,7 +18,7 @@ LL |                 Some(n) => foo(n),
    |                 ^^^^^^^ with this pattern
 
 error: unnecessary nested match
-  --> $DIR/collapsible_match2.rs:15:24
+  --> $DIR/collapsible_match2.rs:20:24
    |
 LL |               Ok(val) => match val {
    |  ________________________^
@@ -28,7 +28,7 @@ LL | |             },
    | |_____________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match2.rs:15:16
+  --> $DIR/collapsible_match2.rs:20:16
    |
 LL |             Ok(val) => match val {
    |                ^^^ replace this binding
@@ -36,7 +36,7 @@ LL |                 Some(n) => foo(n),
    |                 ^^^^^^^ with this pattern
 
 error: unnecessary nested match
-  --> $DIR/collapsible_match2.rs:29:29
+  --> $DIR/collapsible_match2.rs:34:29
    |
 LL |                       $pat => match $e {
    |  _____________________________^
@@ -49,7 +49,7 @@ LL |           mac!(res_opt => Ok(val), val => Some(n), foo(n));
    |           ------------------------------------------------- in this macro invocation
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match2.rs:41:28
+  --> $DIR/collapsible_match2.rs:46:28
    |
 LL |         mac!(res_opt => Ok(val), val => Some(n), foo(n));
    |                            ^^^          ^^^^^^^ with this pattern
@@ -58,7 +58,7 @@ LL |         mac!(res_opt => Ok(val), val => Some(n), foo(n));
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unnecessary nested match
-  --> $DIR/collapsible_match2.rs:46:20
+  --> $DIR/collapsible_match2.rs:51:20
    |
 LL |           Some(s) => match *s {
    |  ____________________^
@@ -68,7 +68,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match2.rs:46:14
+  --> $DIR/collapsible_match2.rs:51:14
    |
 LL |         Some(s) => match *s {
    |              ^ replace this binding
@@ -76,7 +76,7 @@ LL |             [n] => foo(n),
    |             ^^^ with this pattern
 
 error: unnecessary nested match
-  --> $DIR/collapsible_match2.rs:55:24
+  --> $DIR/collapsible_match2.rs:60:24
    |
 LL |           Some(ref s) => match &*s {
    |  ________________________^
@@ -86,7 +86,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match2.rs:55:14
+  --> $DIR/collapsible_match2.rs:60:14
    |
 LL |         Some(ref s) => match &*s {
    |              ^^^^^ replace this binding
diff --git a/tests/ui/crashes/ice-7012.rs b/tests/ui/crashes/ice-7012.rs
new file mode 100644
index 00000000000..60bdbc4f124
--- /dev/null
+++ b/tests/ui/crashes/ice-7012.rs
@@ -0,0 +1,17 @@
+#![allow(clippy::all)]
+
+enum _MyOption {
+    None,
+    Some(()),
+}
+
+impl _MyOption {
+    fn _foo(&self) {
+        match self {
+            &Self::Some(_) => {},
+            _ => {},
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/default_numeric_fallback.rs b/tests/ui/default_numeric_fallback.rs
index 0b3758952ac..43468872db0 100644
--- a/tests/ui/default_numeric_fallback.rs
+++ b/tests/ui/default_numeric_fallback.rs
@@ -3,6 +3,7 @@
 #![allow(clippy::never_loop)]
 #![allow(clippy::no_effect)]
 #![allow(clippy::unnecessary_operation)]
+#![allow(clippy::branches_sharing_code)]
 
 mod basic_expr {
     fn test() {
diff --git a/tests/ui/default_numeric_fallback.stderr b/tests/ui/default_numeric_fallback.stderr
index b31aa4ebcf8..d1c4c8203dd 100644
--- a/tests/ui/default_numeric_fallback.stderr
+++ b/tests/ui/default_numeric_fallback.stderr
@@ -1,5 +1,5 @@
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:10:17
+  --> $DIR/default_numeric_fallback.rs:11:17
    |
 LL |         let x = 22;
    |                 ^^ help: consider adding suffix: `22_i32`
@@ -7,139 +7,139 @@ LL |         let x = 22;
    = note: `-D clippy::default-numeric-fallback` implied by `-D warnings`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:11:18
+  --> $DIR/default_numeric_fallback.rs:12:18
    |
 LL |         let x = [1, 2, 3];
    |                  ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:11:21
+  --> $DIR/default_numeric_fallback.rs:12:21
    |
 LL |         let x = [1, 2, 3];
    |                     ^ help: consider adding suffix: `2_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:11:24
+  --> $DIR/default_numeric_fallback.rs:12:24
    |
 LL |         let x = [1, 2, 3];
    |                        ^ help: consider adding suffix: `3_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:12:28
+  --> $DIR/default_numeric_fallback.rs:13:28
    |
 LL |         let x = if true { (1, 2) } else { (3, 4) };
    |                            ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:12:31
+  --> $DIR/default_numeric_fallback.rs:13:31
    |
 LL |         let x = if true { (1, 2) } else { (3, 4) };
    |                               ^ help: consider adding suffix: `2_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:12:44
+  --> $DIR/default_numeric_fallback.rs:13:44
    |
 LL |         let x = if true { (1, 2) } else { (3, 4) };
    |                                            ^ help: consider adding suffix: `3_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:12:47
+  --> $DIR/default_numeric_fallback.rs:13:47
    |
 LL |         let x = if true { (1, 2) } else { (3, 4) };
    |                                               ^ help: consider adding suffix: `4_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:13:23
+  --> $DIR/default_numeric_fallback.rs:14:23
    |
 LL |         let x = match 1 {
    |                       ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:14:13
+  --> $DIR/default_numeric_fallback.rs:15:13
    |
 LL |             1 => 1,
    |             ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:14:18
+  --> $DIR/default_numeric_fallback.rs:15:18
    |
 LL |             1 => 1,
    |                  ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:15:18
+  --> $DIR/default_numeric_fallback.rs:16:18
    |
 LL |             _ => 2,
    |                  ^ help: consider adding suffix: `2_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:19:17
+  --> $DIR/default_numeric_fallback.rs:20:17
    |
 LL |         let x = 0.12;
    |                 ^^^^ help: consider adding suffix: `0.12_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:37:21
+  --> $DIR/default_numeric_fallback.rs:38:21
    |
 LL |             let y = 1;
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:45:21
+  --> $DIR/default_numeric_fallback.rs:46:21
    |
 LL |             let y = 1;
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:51:21
+  --> $DIR/default_numeric_fallback.rs:52:21
    |
 LL |             let y = 1;
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:63:9
+  --> $DIR/default_numeric_fallback.rs:64:9
    |
 LL |         1
    |         ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:69:27
+  --> $DIR/default_numeric_fallback.rs:70:27
    |
 LL |         let f = || -> _ { 1 };
    |                           ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:73:29
+  --> $DIR/default_numeric_fallback.rs:74:29
    |
 LL |         let f = || -> i32 { 1 };
    |                             ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:87:21
+  --> $DIR/default_numeric_fallback.rs:88:21
    |
 LL |         generic_arg(1);
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:90:32
+  --> $DIR/default_numeric_fallback.rs:91:32
    |
 LL |         let x: _ = generic_arg(1);
    |                                ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:108:28
+  --> $DIR/default_numeric_fallback.rs:109:28
    |
 LL |         GenericStruct { x: 1 };
    |                            ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:111:36
+  --> $DIR/default_numeric_fallback.rs:112:36
    |
 LL |         let _ = GenericStruct { x: 1 };
    |                                    ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback.rs:131:23
+  --> $DIR/default_numeric_fallback.rs:132:23
    |
 LL |         s.generic_arg(1);
    |                       ^ help: consider adding suffix: `1_i32`
diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs
index 8fcb0e8b28d..4e46bf13991 100644
--- a/tests/ui/derive.rs
+++ b/tests/ui/derive.rs
@@ -35,7 +35,6 @@ impl<'a> Clone for Lt<'a> {
     }
 }
 
-// Ok, `Clone` cannot be derived because of the big array
 #[derive(Copy)]
 struct BigArray {
     a: [u8; 65],
@@ -47,7 +46,6 @@ impl Clone for BigArray {
     }
 }
 
-// Ok, function pointers are not always Clone
 #[derive(Copy)]
 struct FnPtr {
     a: fn() -> !,
@@ -59,7 +57,7 @@ impl Clone for FnPtr {
     }
 }
 
-// Ok, generics
+// Ok, Clone trait impl doesn't have constrained generics.
 #[derive(Copy)]
 struct Generic<T> {
     a: T,
@@ -71,4 +69,21 @@ impl<T> Clone for Generic<T> {
     }
 }
 
+#[derive(Copy)]
+struct Generic2<T>(T);
+impl<T: Clone> Clone for Generic2<T> {
+    fn clone(&self) -> Self {
+        Self(self.0.clone())
+    }
+}
+
+// Ok, Clone trait impl doesn't have constrained generics.
+#[derive(Copy)]
+struct GenericRef<'a, T, U>(T, &'a U);
+impl<T: Clone, U> Clone for GenericRef<'_, T, U> {
+    fn clone(&self) -> Self {
+        Self(self.0.clone(), self.1)
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr
index 1328a9b3107..82a70ceecc3 100644
--- a/tests/ui/derive.stderr
+++ b/tests/ui/derive.stderr
@@ -40,7 +40,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:44:1
+  --> $DIR/derive.rs:43:1
    |
 LL | / impl Clone for BigArray {
 LL | |     fn clone(&self) -> Self {
@@ -50,7 +50,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:44:1
+  --> $DIR/derive.rs:43:1
    |
 LL | / impl Clone for BigArray {
 LL | |     fn clone(&self) -> Self {
@@ -60,7 +60,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:56:1
+  --> $DIR/derive.rs:54:1
    |
 LL | / impl Clone for FnPtr {
 LL | |     fn clone(&self) -> Self {
@@ -70,7 +70,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:56:1
+  --> $DIR/derive.rs:54:1
    |
 LL | / impl Clone for FnPtr {
 LL | |     fn clone(&self) -> Self {
@@ -79,5 +79,25 @@ LL | |     }
 LL | | }
    | |_^
 
-error: aborting due to 4 previous errors
+error: you are implementing `Clone` explicitly on a `Copy` type
+  --> $DIR/derive.rs:74:1
+   |
+LL | / impl<T: Clone> Clone for Generic2<T> {
+LL | |     fn clone(&self) -> Self {
+LL | |         Self(self.0.clone())
+LL | |     }
+LL | | }
+   | |_^
+   |
+note: consider deriving `Clone` or removing `Copy`
+  --> $DIR/derive.rs:74:1
+   |
+LL | / impl<T: Clone> Clone for Generic2<T> {
+LL | |     fn clone(&self) -> Self {
+LL | |         Self(self.0.clone())
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs
index d2c666bd290..c946a047f1b 100644
--- a/tests/ui/doc.rs
+++ b/tests/ui/doc.rs
@@ -1,8 +1,8 @@
 //! This file tests for the `DOC_MARKDOWN` lint.
 
-#![allow(dead_code)]
+#![allow(dead_code, incomplete_features)]
 #![warn(clippy::doc_markdown)]
-#![feature(custom_inner_attributes)]
+#![feature(custom_inner_attributes, const_generics, const_evaluatable_checked, const_option)]
 #![rustfmt::skip]
 
 /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
@@ -202,3 +202,20 @@ fn issue_2343() {}
 /// This should not cause an ICE:
 /// __|_ _|__||_|
 fn pulldown_cmark_crash() {}
+
+// issue #7033 - const_evaluatable_checked ICE
+struct S<T, const N: usize>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    arr: [T; N.checked_next_power_of_two().unwrap()],
+    n: usize,
+}
+
+impl<T: Copy + Default, const N: usize> S<T, N>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+    fn new() -> Self {
+        Self {
+            arr: [T::default(); N.checked_next_power_of_two().unwrap()],
+            n: 0,
+        }
+    }
+}
diff --git a/tests/ui/escape_analysis.rs b/tests/ui/escape_analysis.rs
index d26f48fc68f..13e2b6c7a2e 100644
--- a/tests/ui/escape_analysis.rs
+++ b/tests/ui/escape_analysis.rs
@@ -101,7 +101,7 @@ fn warn_match() {
     let x = box A;
     match &x {
         // not moved
-        ref y => (),
+        y => (),
     }
 }
 
@@ -111,7 +111,7 @@ fn nowarn_large_array() {
     let x = box [1; 10000];
     match &x {
         // not moved
-        ref y => (),
+        y => (),
     }
 }
 
diff --git a/tests/ui/floating_point_log.fixed b/tests/ui/floating_point_log.fixed
index 7dc7ee94aff..5b487bb8fcf 100644
--- a/tests/ui/floating_point_log.fixed
+++ b/tests/ui/floating_point_log.fixed
@@ -27,7 +27,7 @@ fn check_ln1p() {
     let _ = (x / 2.0).ln_1p();
     let _ = x.powi(3).ln_1p();
     let _ = (x.powi(3) / 2.0).ln_1p();
-    let _ = ((std::f32::consts::E - 1.0)).ln_1p();
+    let _ = (std::f32::consts::E - 1.0).ln_1p();
     let _ = x.ln_1p();
     let _ = x.powi(3).ln_1p();
     let _ = (x + 2.0).ln_1p();
diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr
index 900dc2b7933..96e5a154441 100644
--- a/tests/ui/floating_point_log.stderr
+++ b/tests/ui/floating_point_log.stderr
@@ -90,7 +90,7 @@ error: ln(1 + x) can be computed more accurately
   --> $DIR/floating_point_log.rs:30:13
    |
 LL |     let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(std::f32::consts::E - 1.0).ln_1p()`
 
 error: ln(1 + x) can be computed more accurately
   --> $DIR/floating_point_log.rs:31:13
diff --git a/tests/ui/from_str_radix_10.stderr b/tests/ui/from_str_radix_10.stderr
index 471bf52a9a7..da5c16f8d01 100644
--- a/tests/ui/from_str_radix_10.stderr
+++ b/tests/ui/from_str_radix_10.stderr
@@ -28,7 +28,7 @@ error: this call to `from_str_radix` can be replaced with a call to `str::parse`
   --> $DIR/from_str_radix_10.rs:32:5
    |
 LL |     u16::from_str_radix(&("10".to_owned() + "5"), 10)?;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(("10".to_owned() + "5")).parse::<u16>()`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `("10".to_owned() + "5").parse::<u16>()`
 
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
   --> $DIR/from_str_radix_10.rs:33:5
diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs
index 9c5fe02f751..ef956745500 100644
--- a/tests/ui/if_same_then_else.rs
+++ b/tests/ui/if_same_then_else.rs
@@ -5,7 +5,8 @@
     clippy::never_loop,
     clippy::no_effect,
     clippy::unused_unit,
-    clippy::zero_divided_by_zero
+    clippy::zero_divided_by_zero,
+    clippy::branches_sharing_code
 )]
 
 struct Foo {
diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr
index d9fdf06fa8b..2f38052fc20 100644
--- a/tests/ui/if_same_then_else.stderr
+++ b/tests/ui/if_same_then_else.stderr
@@ -1,111 +1,111 @@
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:28:12
+  --> $DIR/if_same_then_else.rs:21:13
    |
-LL |       } else {
-   |  ____________^
-LL | |         //~ ERROR same body as `if` block
+LL |       if true {
+   |  _____________^
 LL | |         Foo { bar: 42 };
 LL | |         0..10;
+LL | |         ..;
 ...  |
 LL | |         foo();
-LL | |     }
+LL | |     } else {
    | |_____^
    |
    = note: `-D clippy::if-same-then-else` implied by `-D warnings`
 note: same as this
-  --> $DIR/if_same_then_else.rs:20:13
+  --> $DIR/if_same_then_else.rs:29:12
    |
-LL |       if true {
-   |  _____________^
+LL |       } else {
+   |  ____________^
+LL | |         //~ ERROR same body as `if` block
 LL | |         Foo { bar: 42 };
 LL | |         0..10;
-LL | |         ..;
 ...  |
 LL | |         foo();
-LL | |     } else {
+LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:66:12
-   |
-LL |       } else {
-   |  ____________^
-LL | |         //~ ERROR same body as `if` block
-LL | |         0.0
-LL | |     };
-   | |_____^
-   |
-note: same as this
-  --> $DIR/if_same_then_else.rs:64:21
+  --> $DIR/if_same_then_else.rs:65:21
    |
 LL |       let _ = if true {
    |  _____________________^
 LL | |         0.0
 LL | |     } else {
    | |_____^
-
-error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:73:12
+   |
+note: same as this
+  --> $DIR/if_same_then_else.rs:67:12
    |
 LL |       } else {
    |  ____________^
 LL | |         //~ ERROR same body as `if` block
-LL | |         -0.0
+LL | |         0.0
 LL | |     };
    | |_____^
-   |
-note: same as this
-  --> $DIR/if_same_then_else.rs:71:21
+
+error: this `if` has identical blocks
+  --> $DIR/if_same_then_else.rs:72:21
    |
 LL |       let _ = if true {
    |  _____________________^
 LL | |         -0.0
 LL | |     } else {
    | |_____^
-
-error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:89:12
+   |
+note: same as this
+  --> $DIR/if_same_then_else.rs:74:12
    |
 LL |       } else {
    |  ____________^
 LL | |         //~ ERROR same body as `if` block
-LL | |         42
+LL | |         -0.0
 LL | |     };
    | |_____^
-   |
-note: same as this
-  --> $DIR/if_same_then_else.rs:87:21
+
+error: this `if` has identical blocks
+  --> $DIR/if_same_then_else.rs:88:21
    |
 LL |       let _ = if true {
    |  _____________________^
 LL | |         42
 LL | |     } else {
    | |_____^
-
-error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:101:12
+   |
+note: same as this
+  --> $DIR/if_same_then_else.rs:90:12
    |
 LL |       } else {
    |  ____________^
 LL | |         //~ ERROR same body as `if` block
+LL | |         42
+LL | |     };
+   | |_____^
+
+error: this `if` has identical blocks
+  --> $DIR/if_same_then_else.rs:95:13
+   |
+LL |       if true {
+   |  _____________^
 LL | |         let bar = if true { 42 } else { 43 };
 LL | |
+LL | |         while foo() {
 ...  |
 LL | |         bar + 1;
-LL | |     }
+LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:94:13
+  --> $DIR/if_same_then_else.rs:102:12
    |
-LL |       if true {
-   |  _____________^
+LL |       } else {
+   |  ____________^
+LL | |         //~ ERROR same body as `if` block
 LL | |         let bar = if true { 42 } else { 43 };
 LL | |
-LL | |         while foo() {
 ...  |
 LL | |         bar + 1;
-LL | |     } else {
+LL | |     }
    | |_____^
 
 error: aborting due to 5 previous errors
diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs
index a2ff1b741ca..e4dc5b647df 100644
--- a/tests/ui/if_same_then_else2.rs
+++ b/tests/ui/if_same_then_else2.rs
@@ -5,7 +5,8 @@
     clippy::collapsible_if,
     clippy::ifs_same_cond,
     clippy::needless_return,
-    clippy::single_element_loop
+    clippy::single_element_loop,
+    clippy::branches_sharing_code
 )]
 
 fn if_same_then_else2() -> Result<&'static str, ()> {
diff --git a/tests/ui/if_same_then_else2.stderr b/tests/ui/if_same_then_else2.stderr
index 454322d8aac..6524be0af85 100644
--- a/tests/ui/if_same_then_else2.stderr
+++ b/tests/ui/if_same_then_else2.stderr
@@ -1,19 +1,5 @@
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:21:12
-   |
-LL |       } else {
-   |  ____________^
-LL | |         //~ ERROR same body as `if` block
-LL | |         for _ in &[42] {
-LL | |             let bar: &Option<_> = &Some::<u8>(42);
-...  |
-LL | |         }
-LL | |     }
-   | |_____^
-   |
-   = note: `-D clippy::if-same-then-else` implied by `-D warnings`
-note: same as this
-  --> $DIR/if_same_then_else2.rs:12:13
+  --> $DIR/if_same_then_else2.rs:13:13
    |
 LL |       if true {
    |  _____________^
@@ -24,95 +10,99 @@ LL | |             if foo.is_some() {
 LL | |         }
 LL | |     } else {
    | |_____^
-
-error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:35:12
+   |
+   = note: `-D clippy::if-same-then-else` implied by `-D warnings`
+note: same as this
+  --> $DIR/if_same_then_else2.rs:22:12
    |
 LL |       } else {
    |  ____________^
 LL | |         //~ ERROR same body as `if` block
-LL | |         if let Some(a) = Some(42) {}
+LL | |         for _ in &[42] {
+LL | |             let bar: &Option<_> = &Some::<u8>(42);
+...  |
+LL | |         }
 LL | |     }
    | |_____^
-   |
-note: same as this
-  --> $DIR/if_same_then_else2.rs:33:13
+
+error: this `if` has identical blocks
+  --> $DIR/if_same_then_else2.rs:34:13
    |
 LL |       if true {
    |  _____________^
 LL | |         if let Some(a) = Some(42) {}
 LL | |     } else {
    | |_____^
-
-error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:42:12
+   |
+note: same as this
+  --> $DIR/if_same_then_else2.rs:36:12
    |
 LL |       } else {
    |  ____________^
 LL | |         //~ ERROR same body as `if` block
-LL | |         if let (1, .., 3) = (1, 2, 3) {}
+LL | |         if let Some(a) = Some(42) {}
 LL | |     }
    | |_____^
-   |
-note: same as this
-  --> $DIR/if_same_then_else2.rs:40:13
+
+error: this `if` has identical blocks
+  --> $DIR/if_same_then_else2.rs:41:13
    |
 LL |       if true {
    |  _____________^
 LL | |         if let (1, .., 3) = (1, 2, 3) {}
 LL | |     } else {
    | |_____^
-
-error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:92:12
+   |
+note: same as this
+  --> $DIR/if_same_then_else2.rs:43:12
    |
 LL |       } else {
    |  ____________^
 LL | |         //~ ERROR same body as `if` block
-LL | |         f32::NAN
-LL | |     };
+LL | |         if let (1, .., 3) = (1, 2, 3) {}
+LL | |     }
    | |_____^
-   |
-note: same as this
-  --> $DIR/if_same_then_else2.rs:90:21
+
+error: this `if` has identical blocks
+  --> $DIR/if_same_then_else2.rs:91:21
    |
 LL |       let _ = if true {
    |  _____________________^
 LL | |         f32::NAN
 LL | |     } else {
    | |_____^
-
-error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:99:12
+   |
+note: same as this
+  --> $DIR/if_same_then_else2.rs:93:12
    |
 LL |       } else {
    |  ____________^
 LL | |         //~ ERROR same body as `if` block
-LL | |         Ok("foo")?;
-LL | |     }
+LL | |         f32::NAN
+LL | |     };
    | |_____^
-   |
-note: same as this
-  --> $DIR/if_same_then_else2.rs:97:13
+
+error: this `if` has identical blocks
+  --> $DIR/if_same_then_else2.rs:98:13
    |
 LL |       if true {
    |  _____________^
 LL | |         Ok("foo")?;
 LL | |     } else {
    | |_____^
-
-error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:124:12
+   |
+note: same as this
+  --> $DIR/if_same_then_else2.rs:100:12
    |
 LL |       } else {
    |  ____________^
-LL | |         let foo = "";
-LL | |         return Ok(&foo[0..]);
+LL | |         //~ ERROR same body as `if` block
+LL | |         Ok("foo")?;
 LL | |     }
    | |_____^
-   |
-note: same as this
-  --> $DIR/if_same_then_else2.rs:121:20
+
+error: this `if` has identical blocks
+  --> $DIR/if_same_then_else2.rs:122:20
    |
 LL |       } else if true {
    |  ____________________^
@@ -120,6 +110,16 @@ LL | |         let foo = "";
 LL | |         return Ok(&foo[0..]);
 LL | |     } else {
    | |_____^
+   |
+note: same as this
+  --> $DIR/if_same_then_else2.rs:125:12
+   |
+LL |       } else {
+   |  ____________^
+LL | |         let foo = "";
+LL | |         return Ok(&foo[0..]);
+LL | |     }
+   | |_____^
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/implicit_clone.rs b/tests/ui/implicit_clone.rs
index 19101522163..cef71cf79d7 100644
--- a/tests/ui/implicit_clone.rs
+++ b/tests/ui/implicit_clone.rs
@@ -66,7 +66,7 @@ fn main() {
     let _ = vec.to_vec();
 
     let vec_ref = &vec;
-    let _ = return_owned_from_slice(&vec_ref);
+    let _ = return_owned_from_slice(vec_ref);
     let _ = vec_ref.to_owned();
     let _ = vec_ref.to_vec();
 
diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed
index 7f92d0dbdc9..b77f17944d8 100644
--- a/tests/ui/into_iter_on_ref.fixed
+++ b/tests/ui/into_iter_on_ref.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(clippy::useless_vec)]
+#![allow(clippy::useless_vec, clippy::needless_borrow)]
 #![warn(clippy::into_iter_on_ref)]
 
 struct X;
diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs
index 416056d3fdb..3854bb05af8 100644
--- a/tests/ui/into_iter_on_ref.rs
+++ b/tests/ui/into_iter_on_ref.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(clippy::useless_vec)]
+#![allow(clippy::useless_vec, clippy::needless_borrow)]
 #![warn(clippy::into_iter_on_ref)]
 
 struct X;
diff --git a/tests/ui/len_without_is_empty.rs b/tests/ui/len_without_is_empty.rs
index 6b3636a482e..b9d66347c27 100644
--- a/tests/ui/len_without_is_empty.rs
+++ b/tests/ui/len_without_is_empty.rs
@@ -1,3 +1,5 @@
+// edition:2018
+
 #![warn(clippy::len_without_is_empty)]
 #![allow(dead_code, unused)]
 
@@ -172,9 +174,9 @@ pub trait DependsOnFoo: Foo {
     fn len(&mut self) -> usize;
 }
 
+// issue #1562
 pub struct MultipleImpls;
 
-// issue #1562
 impl MultipleImpls {
     pub fn len(&self) -> usize {
         1
@@ -187,4 +189,99 @@ impl MultipleImpls {
     }
 }
 
+// issue #6958
+pub struct OptionalLen;
+
+impl OptionalLen {
+    pub fn len(&self) -> Option<usize> {
+        Some(0)
+    }
+
+    pub fn is_empty(&self) -> Option<bool> {
+        Some(true)
+    }
+}
+
+pub struct OptionalLen2;
+impl OptionalLen2 {
+    pub fn len(&self) -> Option<usize> {
+        Some(0)
+    }
+
+    pub fn is_empty(&self) -> bool {
+        true
+    }
+}
+
+pub struct OptionalLen3;
+impl OptionalLen3 {
+    pub fn len(&self) -> usize {
+        0
+    }
+
+    // should lint, len is not an option
+    pub fn is_empty(&self) -> Option<bool> {
+        None
+    }
+}
+
+pub struct ResultLen;
+impl ResultLen {
+    pub fn len(&self) -> Result<usize, ()> {
+        Ok(0)
+    }
+
+    // Differing result types
+    pub fn is_empty(&self) -> Option<bool> {
+        Some(true)
+    }
+}
+
+pub struct ResultLen2;
+impl ResultLen2 {
+    pub fn len(&self) -> Result<usize, ()> {
+        Ok(0)
+    }
+
+    pub fn is_empty(&self) -> Result<bool, ()> {
+        Ok(true)
+    }
+}
+
+pub struct ResultLen3;
+impl ResultLen3 {
+    pub fn len(&self) -> Result<usize, ()> {
+        Ok(0)
+    }
+
+    // Non-fallible result is ok.
+    pub fn is_empty(&self) -> bool {
+        true
+    }
+}
+
+pub struct OddLenSig;
+impl OddLenSig {
+    // don't lint
+    pub fn len(&self) -> bool {
+        true
+    }
+}
+
+// issue #6958
+pub struct AsyncLen;
+impl AsyncLen {
+    async fn async_task(&self) -> bool {
+        true
+    }
+
+    pub async fn len(&self) -> usize {
+        if self.async_task().await { 0 } else { 1 }
+    }
+
+    pub async fn is_empty(&self) -> bool {
+        self.len().await == 0
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/len_without_is_empty.stderr b/tests/ui/len_without_is_empty.stderr
index f106506faf4..3282709bcd6 100644
--- a/tests/ui/len_without_is_empty.stderr
+++ b/tests/ui/len_without_is_empty.stderr
@@ -1,5 +1,5 @@
 error: struct `PubOne` has a public `len` method, but no `is_empty` method
-  --> $DIR/len_without_is_empty.rs:7:5
+  --> $DIR/len_without_is_empty.rs:9:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     pub fn len(&self) -> isize {
    = note: `-D clippy::len-without-is-empty` implied by `-D warnings`
 
 error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method
-  --> $DIR/len_without_is_empty.rs:55:1
+  --> $DIR/len_without_is_empty.rs:57:1
    |
 LL | / pub trait PubTraitsToo {
 LL | |     fn len(&self) -> isize;
@@ -15,50 +15,109 @@ LL | | }
    | |_^
 
 error: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` method
-  --> $DIR/len_without_is_empty.rs:68:5
+  --> $DIR/len_without_is_empty.rs:70:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:72:5
+  --> $DIR/len_without_is_empty.rs:74:5
    |
 LL |     fn is_empty(&self) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:80:5
+  --> $DIR/len_without_is_empty.rs:82:5
    |
 LL |     pub fn len(&self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:84:5
+  --> $DIR/len_without_is_empty.rs:86:5
    |
 LL |     pub fn is_empty(&self, x: u32) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(&self) -> bool`
 
 error: struct `MismatchedSelf` has a public `len` method, but the `is_empty` method has an unexpected signature
-  --> $DIR/len_without_is_empty.rs:92:5
+  --> $DIR/len_without_is_empty.rs:94:5
    |
 LL |     pub fn len(self) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `is_empty` defined here
-  --> $DIR/len_without_is_empty.rs:96:5
+  --> $DIR/len_without_is_empty.rs:98:5
    |
 LL |     pub fn is_empty(&self) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature: `(self) -> bool`
 
 error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method
-  --> $DIR/len_without_is_empty.rs:171:1
+  --> $DIR/len_without_is_empty.rs:173:1
    |
 LL | / pub trait DependsOnFoo: Foo {
 LL | |     fn len(&mut self) -> usize;
 LL | | }
    | |_^
 
-error: aborting due to 6 previous errors
+error: struct `OptionalLen3` has a public `len` method, but the `is_empty` method has an unexpected signature
+  --> $DIR/len_without_is_empty.rs:218:5
+   |
+LL |     pub fn len(&self) -> usize {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `is_empty` defined here
+  --> $DIR/len_without_is_empty.rs:223:5
+   |
+LL |     pub fn is_empty(&self) -> Option<bool> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected signature: `(&self) -> bool`
+
+error: struct `ResultLen` has a public `len` method, but the `is_empty` method has an unexpected signature
+  --> $DIR/len_without_is_empty.rs:230:5
+   |
+LL |     pub fn len(&self) -> Result<usize, ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `is_empty` defined here
+  --> $DIR/len_without_is_empty.rs:235:5
+   |
+LL |     pub fn is_empty(&self) -> Option<bool> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected signature: `(&self) -> bool` or `(&self) -> Result<bool>
+
+error: this returns a `Result<_, ()>`
+  --> $DIR/len_without_is_empty.rs:230:5
+   |
+LL |     pub fn len(&self) -> Result<usize, ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::result-unit-err` implied by `-D warnings`
+   = help: use a custom `Error` type instead
+
+error: this returns a `Result<_, ()>`
+  --> $DIR/len_without_is_empty.rs:242:5
+   |
+LL |     pub fn len(&self) -> Result<usize, ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a custom `Error` type instead
+
+error: this returns a `Result<_, ()>`
+  --> $DIR/len_without_is_empty.rs:246:5
+   |
+LL |     pub fn is_empty(&self) -> Result<bool, ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a custom `Error` type instead
+
+error: this returns a `Result<_, ()>`
+  --> $DIR/len_without_is_empty.rs:253:5
+   |
+LL |     pub fn len(&self) -> Result<usize, ()> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a custom `Error` type instead
+
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs
index 32a67f181df..2d8f3c2f0e7 100644
--- a/tests/ui/let_if_seq.rs
+++ b/tests/ui/let_if_seq.rs
@@ -2,7 +2,8 @@
     unused_variables,
     unused_assignments,
     clippy::similar_names,
-    clippy::blacklisted_name
+    clippy::blacklisted_name,
+    clippy::branches_sharing_code
 )]
 #![warn(clippy::useless_let_if_seq)]
 
diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr
index 7de560c7348..9cf2e10a5ee 100644
--- a/tests/ui/let_if_seq.stderr
+++ b/tests/ui/let_if_seq.stderr
@@ -1,5 +1,5 @@
 error: `if _ { .. } else { .. }` is an expression
-  --> $DIR/let_if_seq.rs:64:5
+  --> $DIR/let_if_seq.rs:65:5
    |
 LL | /     let mut foo = 0;
 LL | |     if f() {
@@ -11,7 +11,7 @@ LL | |     }
    = note: you might not need `mut` at all
 
 error: `if _ { .. } else { .. }` is an expression
-  --> $DIR/let_if_seq.rs:69:5
+  --> $DIR/let_if_seq.rs:70:5
    |
 LL | /     let mut bar = 0;
 LL | |     if f() {
@@ -25,7 +25,7 @@ LL | |     }
    = note: you might not need `mut` at all
 
 error: `if _ { .. } else { .. }` is an expression
-  --> $DIR/let_if_seq.rs:77:5
+  --> $DIR/let_if_seq.rs:78:5
    |
 LL | /     let quz;
 LL | |     if f() {
@@ -36,7 +36,7 @@ LL | |     }
    | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };`
 
 error: `if _ { .. } else { .. }` is an expression
-  --> $DIR/let_if_seq.rs:106:5
+  --> $DIR/let_if_seq.rs:107:5
    |
 LL | /     let mut baz = 0;
 LL | |     if f() {
diff --git a/tests/ui/dlist.rs b/tests/ui/linkedlist.rs
index 2940d2d2901..2c3b25cd45e 100644
--- a/tests/ui/dlist.rs
+++ b/tests/ui/linkedlist.rs
@@ -5,6 +5,9 @@
 extern crate alloc;
 use alloc::collections::linked_list::LinkedList;
 
+const C: LinkedList<i32> = LinkedList::new();
+static S: LinkedList<i32> = LinkedList::new();
+
 trait Foo {
     type Baz = LinkedList<u8>;
     fn foo(_: LinkedList<u8>);
diff --git a/tests/ui/dlist.stderr b/tests/ui/linkedlist.stderr
index 234db33ba12..38ae71714d6 100644
--- a/tests/ui/dlist.stderr
+++ b/tests/ui/linkedlist.stderr
@@ -1,14 +1,30 @@
 error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
-  --> $DIR/dlist.rs:9:16
+  --> $DIR/linkedlist.rs:8:10
+   |
+LL | const C: LinkedList<i32> = LinkedList::new();
+   |          ^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::linkedlist` implied by `-D warnings`
+   = help: a `VecDeque` might work
+
+error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
+  --> $DIR/linkedlist.rs:9:11
+   |
+LL | static S: LinkedList<i32> = LinkedList::new();
+   |           ^^^^^^^^^^^^^^^
+   |
+   = help: a `VecDeque` might work
+
+error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
+  --> $DIR/linkedlist.rs:12:16
    |
 LL |     type Baz = LinkedList<u8>;
    |                ^^^^^^^^^^^^^^
    |
-   = note: `-D clippy::linkedlist` implied by `-D warnings`
    = help: a `VecDeque` might work
 
 error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
-  --> $DIR/dlist.rs:10:15
+  --> $DIR/linkedlist.rs:13:15
    |
 LL |     fn foo(_: LinkedList<u8>);
    |               ^^^^^^^^^^^^^^
@@ -16,7 +32,7 @@ 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/dlist.rs:11:23
+  --> $DIR/linkedlist.rs:14:23
    |
 LL |     const BAR: Option<LinkedList<u8>>;
    |                       ^^^^^^^^^^^^^^
@@ -24,7 +40,7 @@ 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/dlist.rs:22:15
+  --> $DIR/linkedlist.rs:25:15
    |
 LL |     fn foo(_: LinkedList<u8>) {}
    |               ^^^^^^^^^^^^^^
@@ -32,7 +48,7 @@ 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/dlist.rs:25:39
+  --> $DIR/linkedlist.rs:28:39
    |
 LL | pub fn test(my_favourite_linked_list: LinkedList<u8>) {
    |                                       ^^^^^^^^^^^^^^
@@ -40,12 +56,12 @@ LL | pub fn test(my_favourite_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/dlist.rs:29:29
+  --> $DIR/linkedlist.rs:32:29
    |
 LL | pub fn test_ret() -> Option<LinkedList<u8>> {
    |                             ^^^^^^^^^^^^^^
    |
    = help: a `VecDeque` might work
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/manual_map_option.fixed b/tests/ui/manual_map_option.fixed
index acb6a580ceb..ee015845777 100644
--- a/tests/ui/manual_map_option.fixed
+++ b/tests/ui/manual_map_option.fixed
@@ -7,6 +7,7 @@
     clippy::map_identity,
     clippy::unit_arg,
     clippy::match_ref_pats,
+    clippy::redundant_pattern_matching,
     dead_code
 )]
 
@@ -130,7 +131,19 @@ fn main() {
     }
 
     // #6847
-    if Some(0).is_some() {
+    if let Some(_) = Some(0) {
         Some(0)
     } else { Some(0).map(|x| x + 1) };
+
+    if true {
+        Some(0)
+    } else { Some(0).map(|x| x + 1) };
+
+    // #6967
+    const fn f4() {
+        match Some(0) {
+            Some(x) => Some(x + 1),
+            None => None,
+        };
+    }
 }
diff --git a/tests/ui/manual_map_option.rs b/tests/ui/manual_map_option.rs
index 3299e617707..29509bddfd9 100644
--- a/tests/ui/manual_map_option.rs
+++ b/tests/ui/manual_map_option.rs
@@ -7,6 +7,7 @@
     clippy::map_identity,
     clippy::unit_arg,
     clippy::match_ref_pats,
+    clippy::redundant_pattern_matching,
     dead_code
 )]
 
@@ -195,4 +196,20 @@ fn main() {
     } else {
         None
     };
+
+    if true {
+        Some(0)
+    } else if let Some(x) = Some(0) {
+        Some(x + 1)
+    } else {
+        None
+    };
+
+    // #6967
+    const fn f4() {
+        match Some(0) {
+            Some(x) => Some(x + 1),
+            None => None,
+        };
+    }
 }
diff --git a/tests/ui/manual_map_option.stderr b/tests/ui/manual_map_option.stderr
index 048ccfb9582..cdc2c0e62a9 100644
--- a/tests/ui/manual_map_option.stderr
+++ b/tests/ui/manual_map_option.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:14:5
+  --> $DIR/manual_map_option.rs:15:5
    |
 LL | /     match Some(0) {
 LL | |         Some(_) => Some(2),
@@ -10,7 +10,7 @@ LL | |     };
    = note: `-D clippy::manual-map` implied by `-D warnings`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:19:5
+  --> $DIR/manual_map_option.rs:20:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => Some(x + 1),
@@ -19,7 +19,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x + 1)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:24:5
+  --> $DIR/manual_map_option.rs:25:5
    |
 LL | /     match Some("") {
 LL | |         Some(x) => Some(x.is_empty()),
@@ -28,7 +28,7 @@ LL | |     };
    | |_____^ help: try this: `Some("").map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:29:5
+  --> $DIR/manual_map_option.rs:30:5
    |
 LL | /     if let Some(x) = Some(0) {
 LL | |         Some(!x)
@@ -38,7 +38,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| !x)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:36:5
+  --> $DIR/manual_map_option.rs:37:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => { Some(std::convert::identity(x)) }
@@ -47,7 +47,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(std::convert::identity)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:41:5
+  --> $DIR/manual_map_option.rs:42:5
    |
 LL | /     match Some(&String::new()) {
 LL | |         Some(x) => Some(str::len(x)),
@@ -56,7 +56,7 @@ LL | |     };
    | |_____^ help: try this: `Some(&String::new()).map(|x| str::len(x))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:51:5
+  --> $DIR/manual_map_option.rs:52:5
    |
 LL | /     match &Some([0, 1]) {
 LL | |         Some(x) => Some(x[0]),
@@ -65,7 +65,7 @@ LL | |     };
    | |_____^ help: try this: `Some([0, 1]).as_ref().map(|x| x[0])`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:56:5
+  --> $DIR/manual_map_option.rs:57:5
    |
 LL | /     match &Some(0) {
 LL | |         &Some(x) => Some(x * 2),
@@ -74,7 +74,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x * 2)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:61:5
+  --> $DIR/manual_map_option.rs:62:5
    |
 LL | /     match Some(String::new()) {
 LL | |         Some(ref x) => Some(x.is_empty()),
@@ -83,7 +83,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:66:5
+  --> $DIR/manual_map_option.rs:67:5
    |
 LL | /     match &&Some(String::new()) {
 LL | |         Some(x) => Some(x.len()),
@@ -92,7 +92,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:71:5
+  --> $DIR/manual_map_option.rs:72:5
    |
 LL | /     match &&Some(0) {
 LL | |         &&Some(x) => Some(x + x),
@@ -101,7 +101,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| x + x)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:84:9
+  --> $DIR/manual_map_option.rs:85:9
    |
 LL | /         match &mut Some(String::new()) {
 LL | |             Some(x) => Some(x.push_str("")),
@@ -110,7 +110,7 @@ LL | |         };
    | |_________^ help: try this: `Some(String::new()).as_mut().map(|x| x.push_str(""))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:90:5
+  --> $DIR/manual_map_option.rs:91:5
    |
 LL | /     match &mut Some(String::new()) {
 LL | |         Some(ref x) => Some(x.len()),
@@ -119,7 +119,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:95:5
+  --> $DIR/manual_map_option.rs:96:5
    |
 LL | /     match &mut &Some(String::new()) {
 LL | |         Some(x) => Some(x.is_empty()),
@@ -128,7 +128,7 @@ LL | |     };
    | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:100:5
+  --> $DIR/manual_map_option.rs:101:5
    |
 LL | /     match Some((0, 1, 2)) {
 LL | |         Some((x, y, z)) => Some(x + y + z),
@@ -137,7 +137,7 @@ LL | |     };
    | |_____^ help: try this: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:105:5
+  --> $DIR/manual_map_option.rs:106:5
    |
 LL | /     match Some([1, 2, 3]) {
 LL | |         Some([first, ..]) => Some(first),
@@ -146,7 +146,7 @@ LL | |     };
    | |_____^ help: try this: `Some([1, 2, 3]).map(|[first, ..]| first)`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:110:5
+  --> $DIR/manual_map_option.rs:111:5
    |
 LL | /     match &Some((String::new(), "test")) {
 LL | |         Some((x, y)) => Some((y, x)),
@@ -155,7 +155,7 @@ LL | |     };
    | |_____^ help: try this: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:168:5
+  --> $DIR/manual_map_option.rs:169:5
    |
 LL | /     match Some(0) {
 LL | |         Some(x) => Some(vec![x]),
@@ -164,7 +164,7 @@ LL | |     };
    | |_____^ help: try this: `Some(0).map(|x| vec![x])`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:173:5
+  --> $DIR/manual_map_option.rs:174:5
    |
 LL | /     match option_env!("") {
 LL | |         Some(x) => Some(String::from(x)),
@@ -172,16 +172,19 @@ LL | |         None => None,
 LL | |     };
    | |_____^ help: try this: `option_env!("").map(String::from)`
 
-error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/manual_map_option.rs:191:12
-   |
-LL |     if let Some(_) = Some(0) {
-   |     -------^^^^^^^---------- help: try this: `if Some(0).is_some()`
+error: manual implementation of `Option::map`
+  --> $DIR/manual_map_option.rs:194:12
    |
-   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
+LL |       } else if let Some(x) = Some(0) {
+   |  ____________^
+LL | |         Some(x + 1)
+LL | |     } else {
+LL | |         None
+LL | |     };
+   | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }`
 
 error: manual implementation of `Option::map`
-  --> $DIR/manual_map_option.rs:193:12
+  --> $DIR/manual_map_option.rs:202:12
    |
 LL |       } else if let Some(x) = Some(0) {
    |  ____________^
diff --git a/tests/ui/manual_memcpy/with_loop_counters.stderr b/tests/ui/manual_memcpy/with_loop_counters.stderr
index 2547b19f5d1..a2f2dfce168 100644
--- a/tests/ui/manual_memcpy/with_loop_counters.stderr
+++ b/tests/ui/manual_memcpy/with_loop_counters.stderr
@@ -43,7 +43,7 @@ LL | /     for i in 3..(3 + src.len()) {
 LL | |         dst[i] = src[count];
 LL | |         count += 1;
 LL | |     }
-   | |_____^ help: try replacing the loop by: `dst[3..((3 + src.len()))].clone_from_slice(&src[..((3 + src.len()) - 3)]);`
+   | |_____^ help: try replacing the loop by: `dst[3..(3 + src.len())].clone_from_slice(&src[..((3 + src.len()) - 3)]);`
 
 error: it looks like you're manually copying between slices
   --> $DIR/with_loop_counters.rs:35:5
diff --git a/tests/ui/match_ref_pats.stderr b/tests/ui/match_ref_pats.stderr
index 52cb4a14b72..67474e65cde 100644
--- a/tests/ui/match_ref_pats.stderr
+++ b/tests/ui/match_ref_pats.stderr
@@ -46,6 +46,14 @@ LL |         Some(v) => println!("{:?}", v),
 LL |         None => println!("none"),
    |
 
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/match_ref_pats.rs:35:12
+   |
+LL |     if let &None = a {
+   |     -------^^^^^---- help: try this: `if a.is_none()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
+
 error: you don't need to add `&` to all patterns
   --> $DIR/match_ref_pats.rs:35:5
    |
@@ -59,6 +67,12 @@ help: instead of prefixing all patterns with `&`, you can dereference the expres
 LL |     if let None = *a {
    |            ^^^^   ^^
 
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/match_ref_pats.rs:40:12
+   |
+LL |     if let &None = &b {
+   |     -------^^^^^----- help: try this: `if b.is_none()`
+
 error: you don't need to add `&` to both the expression and the patterns
   --> $DIR/match_ref_pats.rs:40:5
    |
@@ -87,5 +101,5 @@ LL |         match *foo_variant!(0) {
 LL |             Foo::A => println!("A"),
    |
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/match_wildcard_for_single_variants.fixed b/tests/ui/match_wildcard_for_single_variants.fixed
index d99f9af3faf..31b743f7a18 100644
--- a/tests/ui/match_wildcard_for_single_variants.fixed
+++ b/tests/ui/match_wildcard_for_single_variants.fixed
@@ -108,4 +108,20 @@ fn main() {
         Bar::B => (),
         _ => (),
     };
+
+    //#6984
+    {
+        #![allow(clippy::manual_non_exhaustive)]
+        pub enum Enum {
+            A,
+            B,
+            #[doc(hidden)]
+            __Private,
+        }
+        match Enum::A {
+            Enum::A => (),
+            Enum::B => (),
+            _ => (),
+        }
+    }
 }
diff --git a/tests/ui/match_wildcard_for_single_variants.rs b/tests/ui/match_wildcard_for_single_variants.rs
index 1752a95de4b..d19e6ab7eb2 100644
--- a/tests/ui/match_wildcard_for_single_variants.rs
+++ b/tests/ui/match_wildcard_for_single_variants.rs
@@ -108,4 +108,20 @@ fn main() {
         Bar::B => (),
         _ => (),
     };
+
+    //#6984
+    {
+        #![allow(clippy::manual_non_exhaustive)]
+        pub enum Enum {
+            A,
+            B,
+            #[doc(hidden)]
+            __Private,
+        }
+        match Enum::A {
+            Enum::A => (),
+            Enum::B => (),
+            _ => (),
+        }
+    }
 }
diff --git a/tests/ui/min_rust_version_attr.rs b/tests/ui/min_rust_version_attr.rs
index 0f47f1cbc40..49ace1ca128 100644
--- a/tests/ui/min_rust_version_attr.rs
+++ b/tests/ui/min_rust_version_attr.rs
@@ -123,6 +123,11 @@ fn missing_const_for_fn() -> i32 {
     1
 }
 
+fn unnest_or_patterns() {
+    struct TS(u8, u8);
+    if let TS(0, x) | TS(1, x) = TS(0, 0) {}
+}
+
 fn main() {
     filter_map_next();
     checked_conversion();
@@ -138,6 +143,7 @@ fn main() {
     replace_with_default();
     map_unwrap_or();
     missing_const_for_fn();
+    unnest_or_patterns();
 }
 
 mod meets_msrv {
diff --git a/tests/ui/min_rust_version_attr.stderr b/tests/ui/min_rust_version_attr.stderr
index e3e3b335cbe..8d3575c2da8 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:150:24
+  --> $DIR/min_rust_version_attr.rs:156: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:149:9
+  --> $DIR/min_rust_version_attr.rs:155: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:162:24
+  --> $DIR/min_rust_version_attr.rs:168:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:161:9
+  --> $DIR/min_rust_version_attr.rs:167:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/doc_panics.rs b/tests/ui/missing_panics_doc.rs
index 17e72353f80..2e1379a58a6 100644
--- a/tests/ui/doc_panics.rs
+++ b/tests/ui/missing_panics_doc.rs
@@ -33,6 +33,18 @@ pub fn unreachable_and_panic() {
     if true { unreachable!() } else { panic!() }
 }
 
+/// This needs to be documented
+pub fn assert_eq() {
+    let x = 0;
+    assert_eq!(x, 0);
+}
+
+/// This needs to be documented
+pub fn assert_ne() {
+    let x = 0;
+    assert_ne!(x, 0);
+}
+
 /// This is documented
 ///
 /// # Panics
@@ -83,6 +95,26 @@ pub fn unreachable_amd_panic_documented() {
     if true { unreachable!() } else { panic!() }
 }
 
+/// This is documented
+///
+/// # Panics
+///
+/// Panics if `x` is not 0.
+pub fn assert_eq_documented() {
+    let x = 0;
+    assert_eq!(x, 0);
+}
+
+/// This is documented
+///
+/// # Panics
+///
+/// Panics if `x` is 0.
+pub fn assert_ne_documented() {
+    let x = 0;
+    assert_ne!(x, 0);
+}
+
 /// This is okay because it is private
 fn unwrap_private() {
     let result = Err("Hi");
@@ -112,3 +144,11 @@ fn inner_body_private(opt: Option<u32>) {
 pub fn unreachable() {
     unreachable!("This function panics")
 }
+
+/// #6970.
+/// This is okay because it is expansion of `debug_assert` family.
+pub fn debug_assertions() {
+    debug_assert!(false);
+    debug_assert_eq!(1, 2);
+    debug_assert_ne!(1, 2);
+}
diff --git a/tests/ui/doc_panics.stderr b/tests/ui/missing_panics_doc.stderr
index 2fa88a2f6ec..ba96a6a12b5 100644
--- a/tests/ui/doc_panics.stderr
+++ b/tests/ui/missing_panics_doc.stderr
@@ -1,5 +1,5 @@
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/doc_panics.rs:7:1
+  --> $DIR/missing_panics_doc.rs:7:1
    |
 LL | / pub fn unwrap() {
 LL | |     let result = Err("Hi");
@@ -9,13 +9,13 @@ LL | | }
    |
    = note: `-D clippy::missing-panics-doc` implied by `-D warnings`
 note: first possible panic found here
-  --> $DIR/doc_panics.rs:9:5
+  --> $DIR/missing_panics_doc.rs:9:5
    |
 LL |     result.unwrap()
    |     ^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/doc_panics.rs:13:1
+  --> $DIR/missing_panics_doc.rs:13:1
    |
 LL | / pub fn panic() {
 LL | |     panic!("This function panics")
@@ -23,14 +23,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/doc_panics.rs:14:5
+  --> $DIR/missing_panics_doc.rs:14:5
    |
 LL |     panic!("This function panics")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/doc_panics.rs:18:1
+  --> $DIR/missing_panics_doc.rs:18:1
    |
 LL | / pub fn todo() {
 LL | |     todo!()
@@ -38,14 +38,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/doc_panics.rs:19:5
+  --> $DIR/missing_panics_doc.rs:19:5
    |
 LL |     todo!()
    |     ^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/doc_panics.rs:23:1
+  --> $DIR/missing_panics_doc.rs:23:1
    |
 LL | / pub fn inner_body(opt: Option<u32>) {
 LL | |     opt.map(|x| {
@@ -57,14 +57,14 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/doc_panics.rs:26:13
+  --> $DIR/missing_panics_doc.rs:26:13
    |
 LL |             panic!()
    |             ^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/doc_panics.rs:32:1
+  --> $DIR/missing_panics_doc.rs:32:1
    |
 LL | / pub fn unreachable_and_panic() {
 LL | |     if true { unreachable!() } else { panic!() }
@@ -72,11 +72,43 @@ LL | | }
    | |_^
    |
 note: first possible panic found here
-  --> $DIR/doc_panics.rs:33:39
+  --> $DIR/missing_panics_doc.rs:33:39
    |
 LL |     if true { unreachable!() } else { panic!() }
    |                                       ^^^^^^^^
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 5 previous errors
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:37:1
+   |
+LL | / pub fn assert_eq() {
+LL | |     let x = 0;
+LL | |     assert_eq!(x, 0);
+LL | | }
+   | |_^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:39:5
+   |
+LL |     assert_eq!(x, 0);
+   |     ^^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:43:1
+   |
+LL | / pub fn assert_ne() {
+LL | |     let x = 0;
+LL | |     assert_ne!(x, 0);
+LL | | }
+   | |_^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:45:5
+   |
+LL |     assert_ne!(x, 0);
+   |     ^^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
 
diff --git a/tests/ui/needless_bool/simple.rs b/tests/ui/needless_bool/simple.rs
index e9f1428fc3a..588bb88f446 100644
--- a/tests/ui/needless_bool/simple.rs
+++ b/tests/ui/needless_bool/simple.rs
@@ -4,7 +4,8 @@
     dead_code,
     clippy::no_effect,
     clippy::if_same_then_else,
-    clippy::needless_return
+    clippy::needless_return,
+    clippy::branches_sharing_code
 )]
 
 fn main() {
diff --git a/tests/ui/needless_bool/simple.stderr b/tests/ui/needless_bool/simple.stderr
index c57a8a042fb..0ccc9416bcd 100644
--- a/tests/ui/needless_bool/simple.stderr
+++ b/tests/ui/needless_bool/simple.stderr
@@ -1,5 +1,5 @@
 error: this if-then-else expression will always return true
-  --> $DIR/simple.rs:13:5
+  --> $DIR/simple.rs:14:5
    |
 LL | /     if x {
 LL | |         true
@@ -11,7 +11,7 @@ LL | |     };
    = note: `-D clippy::needless-bool` implied by `-D warnings`
 
 error: this if-then-else expression will always return false
-  --> $DIR/simple.rs:18:5
+  --> $DIR/simple.rs:19:5
    |
 LL | /     if x {
 LL | |         false
@@ -21,7 +21,7 @@ LL | |     };
    | |_____^
 
 error: this if-then-else expression will always return true
-  --> $DIR/simple.rs:33:5
+  --> $DIR/simple.rs:34:5
    |
 LL | /     if x {
 LL | |         return true;
@@ -31,7 +31,7 @@ LL | |     };
    | |_____^
 
 error: this if-then-else expression will always return false
-  --> $DIR/simple.rs:41:5
+  --> $DIR/simple.rs:42:5
    |
 LL | /     if x {
 LL | |         return false;
diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr
index 76e789d9052..c773b841f3b 100644
--- a/tests/ui/needless_collect_indirect.stderr
+++ b/tests/ui/needless_collect_indirect.stderr
@@ -1,9 +1,10 @@
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:5:5
+  --> $DIR/needless_collect_indirect.rs:5:39
    |
-LL | /     let indirect_iter = sample.iter().collect::<Vec<_>>();
-LL | |     indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>();
-   | |____^
+LL |     let indirect_iter = sample.iter().collect::<Vec<_>>();
+   |                                       ^^^^^^^
+LL |     indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>();
+   |     ------------------------- the iterator could be used here instead
    |
    = note: `-D clippy::needless-collect` implied by `-D warnings`
 help: use the original Iterator instead of collecting it and then producing a new one
@@ -13,11 +14,12 @@ LL |     sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:7:5
+  --> $DIR/needless_collect_indirect.rs:7:38
    |
-LL | /     let indirect_len = sample.iter().collect::<VecDeque<_>>();
-LL | |     indirect_len.len();
-   | |____^
+LL |     let indirect_len = sample.iter().collect::<VecDeque<_>>();
+   |                                      ^^^^^^^
+LL |     indirect_len.len();
+   |     ------------------ the iterator could be used here instead
    |
 help: take the original Iterator's count instead of collecting it and finding the length
    |
@@ -26,11 +28,12 @@ LL |     sample.iter().count();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:9:5
+  --> $DIR/needless_collect_indirect.rs:9:40
    |
-LL | /     let indirect_empty = sample.iter().collect::<VecDeque<_>>();
-LL | |     indirect_empty.is_empty();
-   | |____^
+LL |     let indirect_empty = sample.iter().collect::<VecDeque<_>>();
+   |                                        ^^^^^^^
+LL |     indirect_empty.is_empty();
+   |     ------------------------- the iterator could be used here instead
    |
 help: check if the original Iterator has anything instead of collecting it and seeing if it's empty
    |
@@ -39,11 +42,12 @@ LL |     sample.iter().next().is_none();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:11:5
+  --> $DIR/needless_collect_indirect.rs:11:43
    |
-LL | /     let indirect_contains = sample.iter().collect::<VecDeque<_>>();
-LL | |     indirect_contains.contains(&&5);
-   | |____^
+LL |     let indirect_contains = sample.iter().collect::<VecDeque<_>>();
+   |                                           ^^^^^^^
+LL |     indirect_contains.contains(&&5);
+   |     ------------------------------- the iterator could be used here instead
    |
 help: check if the original Iterator contains an element instead of collecting then checking
    |
@@ -52,11 +56,12 @@ LL |     sample.iter().any(|x| x == &5);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:23:5
+  --> $DIR/needless_collect_indirect.rs:23:48
    |
-LL | /     let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
-LL | |     non_copy_contains.contains(&a);
-   | |____^
+LL |     let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
+   |                                                ^^^^^^^
+LL |     non_copy_contains.contains(&a);
+   |     ------------------------------ the iterator could be used here instead
    |
 help: check if the original Iterator contains an element instead of collecting then checking
    |
diff --git a/tests/ui/needless_for_each_fixable.fixed b/tests/ui/needless_for_each_fixable.fixed
new file mode 100644
index 00000000000..f00f9ee4c33
--- /dev/null
+++ b/tests/ui/needless_for_each_fixable.fixed
@@ -0,0 +1,113 @@
+// run-rustfix
+#![warn(clippy::needless_for_each)]
+#![allow(unused, clippy::needless_return, clippy::match_single_binding)]
+
+use std::collections::HashMap;
+
+fn should_lint() {
+    let v: Vec<i32> = Vec::new();
+    let mut acc = 0;
+    for elem in v.iter() {
+        acc += elem;
+    }
+    for elem in v.into_iter() {
+        acc += elem;
+    }
+
+    for elem in [1, 2, 3].iter() {
+        acc += elem;
+    }
+
+    let mut hash_map: HashMap<i32, i32> = HashMap::new();
+    for (k, v) in hash_map.iter() {
+        acc += k + v;
+    }
+    for (k, v) in hash_map.iter_mut() {
+        acc += *k + *v;
+    }
+    for k in hash_map.keys() {
+        acc += k;
+    }
+    for v in hash_map.values() {
+        acc += v;
+    }
+
+    fn my_vec() -> Vec<i32> {
+        Vec::new()
+    }
+    for elem in my_vec().iter() {
+        acc += elem;
+    }
+}
+
+fn should_not_lint() {
+    let v: Vec<i32> = Vec::new();
+    let mut acc = 0;
+
+    // `for_each` argument is not closure.
+    fn print(x: &i32) {
+        println!("{}", x);
+    }
+    v.iter().for_each(print);
+
+    // User defined type.
+    struct MyStruct {
+        v: Vec<i32>,
+    }
+    impl MyStruct {
+        fn iter(&self) -> impl Iterator<Item = &i32> {
+            self.v.iter()
+        }
+    }
+    let s = MyStruct { v: Vec::new() };
+    s.iter().for_each(|elem| {
+        acc += elem;
+    });
+
+    // `for_each` follows long iterator chain.
+    v.iter().chain(v.iter()).for_each(|v| {
+        acc += v;
+    });
+    v.as_slice().iter().for_each(|v| {
+        acc += v;
+    });
+    s.v.iter().for_each(|v| {
+        acc += v;
+    });
+
+    // `return` is used in `Loop` of the closure.
+    v.iter().for_each(|v| {
+        for i in 0..*v {
+            if i == 10 {
+                return;
+            } else {
+                println!("{}", v);
+            }
+        }
+        if *v == 20 {
+            return;
+        } else {
+            println!("{}", v);
+        }
+    });
+
+    // Previously transformed iterator variable.
+    let it = v.iter();
+    it.chain(v.iter()).for_each(|elem| {
+        acc += elem;
+    });
+
+    // `for_each` is not directly in a statement.
+    match 1 {
+        _ => v.iter().for_each(|elem| {
+            acc += elem;
+        }),
+    }
+
+    // `for_each` is in a let bingind.
+    let _ = v.iter().for_each(|elem| {
+        acc += elem;
+    });
+}
+
+fn main() {}
diff --git a/tests/ui/needless_for_each_fixable.rs b/tests/ui/needless_for_each_fixable.rs
new file mode 100644
index 00000000000..1bd400d348b
--- /dev/null
+++ b/tests/ui/needless_for_each_fixable.rs
@@ -0,0 +1,113 @@
+// run-rustfix
+#![warn(clippy::needless_for_each)]
+#![allow(unused, clippy::needless_return, clippy::match_single_binding)]
+
+use std::collections::HashMap;
+
+fn should_lint() {
+    let v: Vec<i32> = Vec::new();
+    let mut acc = 0;
+    v.iter().for_each(|elem| {
+        acc += elem;
+    });
+    v.into_iter().for_each(|elem| {
+        acc += elem;
+    });
+
+    [1, 2, 3].iter().for_each(|elem| {
+        acc += elem;
+    });
+
+    let mut hash_map: HashMap<i32, i32> = HashMap::new();
+    hash_map.iter().for_each(|(k, v)| {
+        acc += k + v;
+    });
+    hash_map.iter_mut().for_each(|(k, v)| {
+        acc += *k + *v;
+    });
+    hash_map.keys().for_each(|k| {
+        acc += k;
+    });
+    hash_map.values().for_each(|v| {
+        acc += v;
+    });
+
+    fn my_vec() -> Vec<i32> {
+        Vec::new()
+    }
+    my_vec().iter().for_each(|elem| {
+        acc += elem;
+    });
+}
+
+fn should_not_lint() {
+    let v: Vec<i32> = Vec::new();
+    let mut acc = 0;
+
+    // `for_each` argument is not closure.
+    fn print(x: &i32) {
+        println!("{}", x);
+    }
+    v.iter().for_each(print);
+
+    // User defined type.
+    struct MyStruct {
+        v: Vec<i32>,
+    }
+    impl MyStruct {
+        fn iter(&self) -> impl Iterator<Item = &i32> {
+            self.v.iter()
+        }
+    }
+    let s = MyStruct { v: Vec::new() };
+    s.iter().for_each(|elem| {
+        acc += elem;
+    });
+
+    // `for_each` follows long iterator chain.
+    v.iter().chain(v.iter()).for_each(|v| {
+        acc += v;
+    });
+    v.as_slice().iter().for_each(|v| {
+        acc += v;
+    });
+    s.v.iter().for_each(|v| {
+        acc += v;
+    });
+
+    // `return` is used in `Loop` of the closure.
+    v.iter().for_each(|v| {
+        for i in 0..*v {
+            if i == 10 {
+                return;
+            } else {
+                println!("{}", v);
+            }
+        }
+        if *v == 20 {
+            return;
+        } else {
+            println!("{}", v);
+        }
+    });
+
+    // Previously transformed iterator variable.
+    let it = v.iter();
+    it.chain(v.iter()).for_each(|elem| {
+        acc += elem;
+    });
+
+    // `for_each` is not directly in a statement.
+    match 1 {
+        _ => v.iter().for_each(|elem| {
+            acc += elem;
+        }),
+    }
+
+    // `for_each` is in a let bingind.
+    let _ = v.iter().for_each(|elem| {
+        acc += elem;
+    });
+}
+
+fn main() {}
diff --git a/tests/ui/needless_for_each_fixable.stderr b/tests/ui/needless_for_each_fixable.stderr
new file mode 100644
index 00000000000..483a5e6d61d
--- /dev/null
+++ b/tests/ui/needless_for_each_fixable.stderr
@@ -0,0 +1,123 @@
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_fixable.rs:10:5
+   |
+LL | /     v.iter().for_each(|elem| {
+LL | |         acc += elem;
+LL | |     });
+   | |_______^
+   |
+   = note: `-D clippy::needless-for-each` implied by `-D warnings`
+help: try
+   |
+LL |     for elem in v.iter() {
+LL |         acc += elem;
+LL |     }
+   |
+
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_fixable.rs:13:5
+   |
+LL | /     v.into_iter().for_each(|elem| {
+LL | |         acc += elem;
+LL | |     });
+   | |_______^
+   |
+help: try
+   |
+LL |     for elem in v.into_iter() {
+LL |         acc += elem;
+LL |     }
+   |
+
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_fixable.rs:17:5
+   |
+LL | /     [1, 2, 3].iter().for_each(|elem| {
+LL | |         acc += elem;
+LL | |     });
+   | |_______^
+   |
+help: try
+   |
+LL |     for elem in [1, 2, 3].iter() {
+LL |         acc += elem;
+LL |     }
+   |
+
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_fixable.rs:22:5
+   |
+LL | /     hash_map.iter().for_each(|(k, v)| {
+LL | |         acc += k + v;
+LL | |     });
+   | |_______^
+   |
+help: try
+   |
+LL |     for (k, v) in hash_map.iter() {
+LL |         acc += k + v;
+LL |     }
+   |
+
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_fixable.rs:25:5
+   |
+LL | /     hash_map.iter_mut().for_each(|(k, v)| {
+LL | |         acc += *k + *v;
+LL | |     });
+   | |_______^
+   |
+help: try
+   |
+LL |     for (k, v) in hash_map.iter_mut() {
+LL |         acc += *k + *v;
+LL |     }
+   |
+
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_fixable.rs:28:5
+   |
+LL | /     hash_map.keys().for_each(|k| {
+LL | |         acc += k;
+LL | |     });
+   | |_______^
+   |
+help: try
+   |
+LL |     for k in hash_map.keys() {
+LL |         acc += k;
+LL |     }
+   |
+
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_fixable.rs:31:5
+   |
+LL | /     hash_map.values().for_each(|v| {
+LL | |         acc += v;
+LL | |     });
+   | |_______^
+   |
+help: try
+   |
+LL |     for v in hash_map.values() {
+LL |         acc += v;
+LL |     }
+   |
+
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_fixable.rs:38:5
+   |
+LL | /     my_vec().iter().for_each(|elem| {
+LL | |         acc += elem;
+LL | |     });
+   | |_______^
+   |
+help: try
+   |
+LL |     for elem in my_vec().iter() {
+LL |         acc += elem;
+LL |     }
+   |
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/needless_for_each_unfixable.rs b/tests/ui/needless_for_each_unfixable.rs
new file mode 100644
index 00000000000..d765d7dab65
--- /dev/null
+++ b/tests/ui/needless_for_each_unfixable.rs
@@ -0,0 +1,14 @@
+#![warn(clippy::needless_for_each)]
+#![allow(clippy::needless_return)]
+
+fn main() {
+    let v: Vec<i32> = Vec::new();
+    // This is unfixable because the closure includes `return`.
+    v.iter().for_each(|v| {
+        if *v == 10 {
+            return;
+        } else {
+            println!("{}", v);
+        }
+    });
+}
diff --git a/tests/ui/needless_for_each_unfixable.stderr b/tests/ui/needless_for_each_unfixable.stderr
new file mode 100644
index 00000000000..8c4507d2328
--- /dev/null
+++ b/tests/ui/needless_for_each_unfixable.stderr
@@ -0,0 +1,29 @@
+error: needless use of `for_each`
+  --> $DIR/needless_for_each_unfixable.rs:7:5
+   |
+LL | /     v.iter().for_each(|v| {
+LL | |         if *v == 10 {
+LL | |             return;
+LL | |         } else {
+LL | |             println!("{}", v);
+LL | |         }
+LL | |     });
+   | |_______^
+   |
+   = note: `-D clippy::needless-for-each` implied by `-D warnings`
+help: try
+   |
+LL |     for v in v.iter() {
+LL |         if *v == 10 {
+LL |             return;
+LL |         } else {
+LL |             println!("{}", v);
+LL |         }
+ ...
+help: ...and replace `return` with `continue`
+   |
+LL |             continue;
+   |             ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed
index 990475fcb58..82d95cc041f 100644
--- a/tests/ui/needless_return.fixed
+++ b/tests/ui/needless_return.fixed
@@ -1,7 +1,12 @@
 // run-rustfix
 
-#![allow(unused, clippy::needless_bool)]
-#![allow(clippy::if_same_then_else, clippy::single_match)]
+#![allow(unused)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::single_match,
+    clippy::branches_sharing_code,
+    clippy::needless_bool
+)]
 #![warn(clippy::needless_return)]
 
 macro_rules! the_answer {
diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs
index dec3d84a020..8a471f802e1 100644
--- a/tests/ui/needless_return.rs
+++ b/tests/ui/needless_return.rs
@@ -1,7 +1,12 @@
 // run-rustfix
 
-#![allow(unused, clippy::needless_bool)]
-#![allow(clippy::if_same_then_else, clippy::single_match)]
+#![allow(unused)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::single_match,
+    clippy::branches_sharing_code,
+    clippy::needless_bool
+)]
 #![warn(clippy::needless_return)]
 
 macro_rules! the_answer {
diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr
index ae31d607541..075db22456f 100644
--- a/tests/ui/needless_return.stderr
+++ b/tests/ui/needless_return.stderr
@@ -1,5 +1,5 @@
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:18:5
+  --> $DIR/needless_return.rs:23:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
@@ -7,103 +7,103 @@ LL |     return true;
    = note: `-D clippy::needless-return` implied by `-D warnings`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:22:5
+  --> $DIR/needless_return.rs:27:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:27:9
+  --> $DIR/needless_return.rs:32:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:29:9
+  --> $DIR/needless_return.rs:34:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:35:17
+  --> $DIR/needless_return.rs:40:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:37:13
+  --> $DIR/needless_return.rs:42:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:44:9
+  --> $DIR/needless_return.rs:49:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:46:16
+  --> $DIR/needless_return.rs:51:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:54:5
+  --> $DIR/needless_return.rs:59:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:59:9
+  --> $DIR/needless_return.rs:64:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:61:9
+  --> $DIR/needless_return.rs:66:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:68:14
+  --> $DIR/needless_return.rs:73:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:83:9
+  --> $DIR/needless_return.rs:88:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:85:9
+  --> $DIR/needless_return.rs:90:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:106:32
+  --> $DIR/needless_return.rs:111:32
    |
 LL |         bar.unwrap_or_else(|_| return)
    |                                ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:111:13
+  --> $DIR/needless_return.rs:116:13
    |
 LL |             return;
    |             ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:113:20
+  --> $DIR/needless_return.rs:118:20
    |
 LL |         let _ = || return;
    |                    ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:119:32
+  --> $DIR/needless_return.rs:124:32
    |
 LL |         res.unwrap_or_else(|_| return Foo)
    |                                ^^^^^^^^^^ help: remove `return`: `Foo`
diff --git a/tests/ui/non_octal_unix_permissions.fixed b/tests/ui/non_octal_unix_permissions.fixed
new file mode 100644
index 00000000000..a9b2dcfb085
--- /dev/null
+++ b/tests/ui/non_octal_unix_permissions.fixed
@@ -0,0 +1,33 @@
+// ignore-windows
+// run-rustfix
+#![warn(clippy::non_octal_unix_permissions)]
+use std::fs::{DirBuilder, File, OpenOptions, Permissions};
+use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt, PermissionsExt};
+
+fn main() {
+    let permissions = 0o760;
+
+    // OpenOptionsExt::mode
+    let mut options = OpenOptions::new();
+    options.mode(0o440);
+    options.mode(0o400);
+    options.mode(permissions);
+
+    // PermissionsExt::from_mode
+    let _permissions = Permissions::from_mode(0o647);
+    let _permissions = Permissions::from_mode(0o000);
+    let _permissions = Permissions::from_mode(permissions);
+
+    // PermissionsExt::set_mode
+    let f = File::create("foo.txt").unwrap();
+    let metadata = f.metadata().unwrap();
+    let mut permissions = metadata.permissions();
+
+    permissions.set_mode(0o644);
+    permissions.set_mode(0o704);
+
+    // DirBuilderExt::mode
+    let mut builder = DirBuilder::new();
+    builder.mode(0o755);
+    builder.mode(0o406);
+}
diff --git a/tests/ui/non_octal_unix_permissions.rs b/tests/ui/non_octal_unix_permissions.rs
new file mode 100644
index 00000000000..7d2922f494e
--- /dev/null
+++ b/tests/ui/non_octal_unix_permissions.rs
@@ -0,0 +1,33 @@
+// ignore-windows
+// run-rustfix
+#![warn(clippy::non_octal_unix_permissions)]
+use std::fs::{DirBuilder, File, OpenOptions, Permissions};
+use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt, PermissionsExt};
+
+fn main() {
+    let permissions = 0o760;
+
+    // OpenOptionsExt::mode
+    let mut options = OpenOptions::new();
+    options.mode(440);
+    options.mode(0o400);
+    options.mode(permissions);
+
+    // PermissionsExt::from_mode
+    let _permissions = Permissions::from_mode(647);
+    let _permissions = Permissions::from_mode(0o000);
+    let _permissions = Permissions::from_mode(permissions);
+
+    // PermissionsExt::set_mode
+    let f = File::create("foo.txt").unwrap();
+    let metadata = f.metadata().unwrap();
+    let mut permissions = metadata.permissions();
+
+    permissions.set_mode(644);
+    permissions.set_mode(0o704);
+
+    // DirBuilderExt::mode
+    let mut builder = DirBuilder::new();
+    builder.mode(755);
+    builder.mode(0o406);
+}
diff --git a/tests/ui/non_octal_unix_permissions.stderr b/tests/ui/non_octal_unix_permissions.stderr
new file mode 100644
index 00000000000..32845d06594
--- /dev/null
+++ b/tests/ui/non_octal_unix_permissions.stderr
@@ -0,0 +1,28 @@
+error: using a non-octal value to set unix file permissions
+  --> $DIR/non_octal_unix_permissions.rs:12:18
+   |
+LL |     options.mode(440);
+   |                  ^^^ help: consider using an octal literal instead: `0o440`
+   |
+   = note: `-D clippy::non-octal-unix-permissions` implied by `-D warnings`
+
+error: using a non-octal value to set unix file permissions
+  --> $DIR/non_octal_unix_permissions.rs:17:47
+   |
+LL |     let _permissions = Permissions::from_mode(647);
+   |                                               ^^^ help: consider using an octal literal instead: `0o647`
+
+error: using a non-octal value to set unix file permissions
+  --> $DIR/non_octal_unix_permissions.rs:26:26
+   |
+LL |     permissions.set_mode(644);
+   |                          ^^^ help: consider using an octal literal instead: `0o644`
+
+error: using a non-octal value to set unix file permissions
+  --> $DIR/non_octal_unix_permissions.rs:31:18
+   |
+LL |     builder.mode(755);
+   |                  ^^^ help: consider using an octal literal instead: `0o755`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/option_filter_map.fixed b/tests/ui/option_filter_map.fixed
new file mode 100644
index 00000000000..f9d1825ade0
--- /dev/null
+++ b/tests/ui/option_filter_map.fixed
@@ -0,0 +1,23 @@
+#![warn(clippy::option_filter_map)]
+// run-rustfix
+fn odds_out(x: i32) -> Option<i32> {
+    if x % 2 == 0 { Some(x) } else { None }
+}
+
+fn main() {
+    let _ = Some(Some(1)).flatten();
+    let _ = Some(Some(1)).flatten();
+    let _ = Some(1).map(odds_out).flatten();
+    let _ = Some(1).map(odds_out).flatten();
+
+    let _ = vec![Some(1)].into_iter().flatten();
+    let _ = vec![Some(1)].into_iter().flatten();
+    let _ = vec![1]
+        .into_iter()
+        .map(odds_out)
+        .flatten();
+    let _ = vec![1]
+        .into_iter()
+        .map(odds_out)
+        .flatten();
+}
diff --git a/tests/ui/option_filter_map.rs b/tests/ui/option_filter_map.rs
new file mode 100644
index 00000000000..588e1ccccce
--- /dev/null
+++ b/tests/ui/option_filter_map.rs
@@ -0,0 +1,25 @@
+#![warn(clippy::option_filter_map)]
+// run-rustfix
+fn odds_out(x: i32) -> Option<i32> {
+    if x % 2 == 0 { Some(x) } else { None }
+}
+
+fn main() {
+    let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap);
+    let _ = Some(Some(1)).filter(|o| o.is_some()).map(|o| o.unwrap());
+    let _ = Some(1).map(odds_out).filter(Option::is_some).map(Option::unwrap);
+    let _ = Some(1).map(odds_out).filter(|o| o.is_some()).map(|o| o.unwrap());
+
+    let _ = vec![Some(1)].into_iter().filter(Option::is_some).map(Option::unwrap);
+    let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()).map(|o| o.unwrap());
+    let _ = vec![1]
+        .into_iter()
+        .map(odds_out)
+        .filter(Option::is_some)
+        .map(Option::unwrap);
+    let _ = vec![1]
+        .into_iter()
+        .map(odds_out)
+        .filter(|o| o.is_some())
+        .map(|o| o.unwrap());
+}
diff --git a/tests/ui/option_filter_map.stderr b/tests/ui/option_filter_map.stderr
new file mode 100644
index 00000000000..31a82969d5a
--- /dev/null
+++ b/tests/ui/option_filter_map.stderr
@@ -0,0 +1,56 @@
+error: `filter` for `Some` followed by `unwrap`
+  --> $DIR/option_filter_map.rs:8:27
+   |
+LL |     let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+   |
+   = note: `-D clippy::option-filter-map` implied by `-D warnings`
+
+error: `filter` for `Some` followed by `unwrap`
+  --> $DIR/option_filter_map.rs:9:27
+   |
+LL |     let _ = Some(Some(1)).filter(|o| o.is_some()).map(|o| o.unwrap());
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `Some` followed by `unwrap`
+  --> $DIR/option_filter_map.rs:10:35
+   |
+LL |     let _ = Some(1).map(odds_out).filter(Option::is_some).map(Option::unwrap);
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `Some` followed by `unwrap`
+  --> $DIR/option_filter_map.rs:11:35
+   |
+LL |     let _ = Some(1).map(odds_out).filter(|o| o.is_some()).map(|o| o.unwrap());
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `Some` followed by `unwrap`
+  --> $DIR/option_filter_map.rs:13:39
+   |
+LL |     let _ = vec![Some(1)].into_iter().filter(Option::is_some).map(Option::unwrap);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `Some` followed by `unwrap`
+  --> $DIR/option_filter_map.rs:14:39
+   |
+LL |     let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()).map(|o| o.unwrap());
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `Some` followed by `unwrap`
+  --> $DIR/option_filter_map.rs:18:10
+   |
+LL |           .filter(Option::is_some)
+   |  __________^
+LL | |         .map(Option::unwrap);
+   | |____________________________^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `Some` followed by `unwrap`
+  --> $DIR/option_filter_map.rs:23:10
+   |
+LL |           .filter(|o| o.is_some())
+   |  __________^
+LL | |         .map(|o| o.unwrap());
+   | |____________________________^ help: consider using `flatten` instead: `flatten()`
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs
index 6859ba8e5bb..2faab9e035d 100644
--- a/tests/ui/option_option.rs
+++ b/tests/ui/option_option.rs
@@ -1,6 +1,9 @@
 #![deny(clippy::option_option)]
 #![allow(clippy::unnecessary_wraps)]
 
+const C: Option<Option<i32>> = None;
+static S: Option<Option<i32>> = None;
+
 fn input(_: Option<Option<u8>>) {}
 
 fn output() -> Option<Option<u8>> {
diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr
index ad7f081c713..a925bb35b04 100644
--- a/tests/ui/option_option.stderr
+++ b/tests/ui/option_option.stderr
@@ -1,8 +1,8 @@
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:4:13
+  --> $DIR/option_option.rs:4:10
    |
-LL | fn input(_: Option<Option<u8>>) {}
-   |             ^^^^^^^^^^^^^^^^^^
+LL | const C: Option<Option<i32>> = None;
+   |          ^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/option_option.rs:1:9
@@ -11,58 +11,70 @@ LL | #![deny(clippy::option_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:6:16
+  --> $DIR/option_option.rs:5:11
+   |
+LL | static S: Option<Option<i32>> = None;
+   |           ^^^^^^^^^^^^^^^^^^^
+
+error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
+  --> $DIR/option_option.rs:7:13
+   |
+LL | fn input(_: Option<Option<u8>>) {}
+   |             ^^^^^^^^^^^^^^^^^^
+
+error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
+  --> $DIR/option_option.rs:9:16
    |
 LL | fn output() -> Option<Option<u8>> {
    |                ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:10:27
+  --> $DIR/option_option.rs:13:27
    |
 LL | fn output_nested() -> Vec<Option<Option<u8>>> {
    |                           ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:15:30
+  --> $DIR/option_option.rs:18:30
    |
 LL | fn output_nested_nested() -> Option<Option<Option<u8>>> {
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:20:8
+  --> $DIR/option_option.rs:23:8
    |
 LL |     x: Option<Option<u8>>,
    |        ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:24:23
+  --> $DIR/option_option.rs:27:23
    |
 LL |     fn struct_fn() -> Option<Option<u8>> {
    |                       ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:30:22
+  --> $DIR/option_option.rs:33:22
    |
 LL |     fn trait_fn() -> Option<Option<u8>>;
    |                      ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:34:11
+  --> $DIR/option_option.rs:37:11
    |
 LL |     Tuple(Option<Option<u8>>),
    |           ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:35:17
+  --> $DIR/option_option.rs:38:17
    |
 LL |     Struct { x: Option<Option<u8>> },
    |                 ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> $DIR/option_option.rs:76:14
+  --> $DIR/option_option.rs:79:14
    |
 LL |         foo: Option<Option<Cow<'a, str>>>,
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 10 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed
index ec309109ed5..f5da703cd1d 100644
--- a/tests/ui/redundant_clone.fixed
+++ b/tests/ui/redundant_clone.fixed
@@ -54,6 +54,7 @@ fn main() {
     not_consumed();
     issue_5405();
     manually_drop();
+    clone_then_move_cloned();
 }
 
 #[derive(Clone)]
@@ -182,3 +183,26 @@ fn manually_drop() {
         Arc::from_raw(p);
     }
 }
+
+fn clone_then_move_cloned() {
+    // issue #5973
+    let x = Some(String::new());
+    // ok, x is moved while the clone is in use.
+    assert_eq!(x.clone(), None, "not equal {}", x.unwrap());
+
+    // issue #5595
+    fn foo<F: Fn()>(_: &Alpha, _: F) {}
+    let x = Alpha;
+    // ok, data is moved while the clone is in use.
+    foo(&x.clone(), move || {
+        let _ = x;
+    });
+
+    // issue #6998
+    struct S(String);
+    impl S {
+        fn m(&mut self) {}
+    }
+    let mut x = S(String::new());
+    x.0.clone().chars().for_each(|_| x.m());
+}
diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs
index b57027456e0..fd7f31a1cc5 100644
--- a/tests/ui/redundant_clone.rs
+++ b/tests/ui/redundant_clone.rs
@@ -54,6 +54,7 @@ fn main() {
     not_consumed();
     issue_5405();
     manually_drop();
+    clone_then_move_cloned();
 }
 
 #[derive(Clone)]
@@ -182,3 +183,26 @@ fn manually_drop() {
         Arc::from_raw(p);
     }
 }
+
+fn clone_then_move_cloned() {
+    // issue #5973
+    let x = Some(String::new());
+    // ok, x is moved while the clone is in use.
+    assert_eq!(x.clone(), None, "not equal {}", x.unwrap());
+
+    // issue #5595
+    fn foo<F: Fn()>(_: &Alpha, _: F) {}
+    let x = Alpha;
+    // ok, data is moved while the clone is in use.
+    foo(&x.clone(), move || {
+        let _ = x;
+    });
+
+    // issue #6998
+    struct S(String);
+    impl S {
+        fn m(&mut self) {}
+    }
+    let mut x = S(String::new());
+    x.0.clone().chars().for_each(|_| x.m());
+}
diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr
index 821e7934be8..529a6de91e2 100644
--- a/tests/ui/redundant_clone.stderr
+++ b/tests/ui/redundant_clone.stderr
@@ -108,61 +108,61 @@ LL |     let _t = tup.0.clone();
    |              ^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:62:25
+  --> $DIR/redundant_clone.rs:63:25
    |
 LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
    |                         ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:62:24
+  --> $DIR/redundant_clone.rs:63:24
    |
 LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
    |                        ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:119:15
+  --> $DIR/redundant_clone.rs:120:15
    |
 LL |     let _s = s.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:119:14
+  --> $DIR/redundant_clone.rs:120:14
    |
 LL |     let _s = s.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:120:15
+  --> $DIR/redundant_clone.rs:121:15
    |
 LL |     let _t = t.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:120:14
+  --> $DIR/redundant_clone.rs:121:14
    |
 LL |     let _t = t.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:130:19
+  --> $DIR/redundant_clone.rs:131:19
    |
 LL |         let _f = f.clone();
    |                   ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:130:18
+  --> $DIR/redundant_clone.rs:131:18
    |
 LL |         let _f = f.clone();
    |                  ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:142:14
+  --> $DIR/redundant_clone.rs:143:14
    |
 LL |     let y = x.clone().join("matthias");
    |              ^^^^^^^^ help: remove this
    |
 note: cloned value is neither consumed nor mutated
-  --> $DIR/redundant_clone.rs:142:13
+  --> $DIR/redundant_clone.rs:143:13
    |
 LL |     let y = x.clone().join("matthias");
    |             ^^^^^^^^^
diff --git a/tests/ui/redundant_slicing.rs b/tests/ui/redundant_slicing.rs
index 922b8b4ce57..554b6ba36ae 100644
--- a/tests/ui/redundant_slicing.rs
+++ b/tests/ui/redundant_slicing.rs
@@ -2,10 +2,31 @@
 #![warn(clippy::redundant_slicing)]
 
 fn main() {
-    let x: &[u32] = &[0];
-    let err = &x[..];
+    let slice: &[u32] = &[0];
+    let _ = &slice[..];
 
     let v = vec![0];
-    let ok = &v[..];
-    let err = &(&v[..])[..];
+    let _ = &v[..]; // Changes the type
+    let _ = &(&v[..])[..]; // Outer borrow is redundant
+
+    static S: &[u8] = &[0, 1, 2];
+    let err = &mut &S[..]; // Should reborrow instead of slice
+
+    let mut vec = vec![0];
+    let mut_slice = &mut *vec;
+    let _ = &mut mut_slice[..]; // Should reborrow instead of slice
+
+    macro_rules! m {
+        ($e:expr) => {
+            $e
+        };
+    }
+    let _ = &m!(slice)[..];
+
+    macro_rules! m2 {
+        ($e:expr) => {
+            &$e[..]
+        };
+    }
+    let _ = m2!(slice); // Don't lint in a macro
 }
diff --git a/tests/ui/redundant_slicing.stderr b/tests/ui/redundant_slicing.stderr
index 9efd6484ad0..bbd10eafbbe 100644
--- a/tests/ui/redundant_slicing.stderr
+++ b/tests/ui/redundant_slicing.stderr
@@ -1,16 +1,34 @@
 error: redundant slicing of the whole range
-  --> $DIR/redundant_slicing.rs:6:15
+  --> $DIR/redundant_slicing.rs:6:13
    |
-LL |     let err = &x[..];
-   |               ^^^^^^ help: use the original slice instead: `x`
+LL |     let _ = &slice[..];
+   |             ^^^^^^^^^^ help: use the original value instead: `slice`
    |
    = note: `-D clippy::redundant-slicing` implied by `-D warnings`
 
 error: redundant slicing of the whole range
-  --> $DIR/redundant_slicing.rs:10:15
+  --> $DIR/redundant_slicing.rs:10:13
    |
-LL |     let err = &(&v[..])[..];
-   |               ^^^^^^^^^^^^^ help: use the original slice instead: `(&v[..])`
+LL |     let _ = &(&v[..])[..]; // Outer borrow is redundant
+   |             ^^^^^^^^^^^^^ help: use the original value instead: `(&v[..])`
 
-error: aborting due to 2 previous errors
+error: redundant slicing of the whole range
+  --> $DIR/redundant_slicing.rs:13:20
+   |
+LL |     let err = &mut &S[..]; // Should reborrow instead of slice
+   |                    ^^^^^^ help: reborrow the original value instead: `&*S`
+
+error: redundant slicing of the whole range
+  --> $DIR/redundant_slicing.rs:17:13
+   |
+LL |     let _ = &mut mut_slice[..]; // Should reborrow instead of slice
+   |             ^^^^^^^^^^^^^^^^^^ help: reborrow the original value instead: `&mut *mut_slice`
+
+error: redundant slicing of the whole range
+  --> $DIR/redundant_slicing.rs:24:13
+   |
+LL |     let _ = &m!(slice)[..];
+   |             ^^^^^^^^^^^^^^ help: use the original value instead: `slice`
+
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/ref_option_ref.rs b/tests/ui/ref_option_ref.rs
index b2c275d68af..2df45c927d7 100644
--- a/tests/ui/ref_option_ref.rs
+++ b/tests/ui/ref_option_ref.rs
@@ -9,7 +9,7 @@
 static THRESHOLD: i32 = 10;
 static REF_THRESHOLD: &Option<&i32> = &Some(&THRESHOLD);
 const CONST_THRESHOLD: &i32 = &10;
-const REF_CONST: &Option<&i32> = &Some(&CONST_THRESHOLD);
+const REF_CONST: &Option<&i32> = &Some(CONST_THRESHOLD);
 
 type RefOptRefU32<'a> = &'a Option<&'a u32>;
 type RefOptRef<'a, T> = &'a Option<&'a T>;
diff --git a/tests/ui/ref_option_ref.stderr b/tests/ui/ref_option_ref.stderr
index 4e7fc800061..b61334758e8 100644
--- a/tests/ui/ref_option_ref.stderr
+++ b/tests/ui/ref_option_ref.stderr
@@ -9,7 +9,7 @@ LL | static REF_THRESHOLD: &Option<&i32> = &Some(&THRESHOLD);
 error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>`
   --> $DIR/ref_option_ref.rs:12:18
    |
-LL | const REF_CONST: &Option<&i32> = &Some(&CONST_THRESHOLD);
+LL | const REF_CONST: &Option<&i32> = &Some(CONST_THRESHOLD);
    |                  ^^^^^^^^^^^^^ help: try: `Option<&i32>`
 
 error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>`
diff --git a/tests/ui/result_unit_error.stderr b/tests/ui/result_unit_error.stderr
index 41d8b0a7cb7..8c7573eabda 100644
--- a/tests/ui/result_unit_error.stderr
+++ b/tests/ui/result_unit_error.stderr
@@ -1,43 +1,43 @@
-error: this returns a `Result<_, ()>
+error: this returns a `Result<_, ()>`
   --> $DIR/result_unit_error.rs:3:1
    |
 LL | pub fn returns_unit_error() -> Result<u32, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::result-unit-err` implied by `-D warnings`
-   = help: use a custom Error type instead
+   = help: use a custom `Error` type instead
 
-error: this returns a `Result<_, ()>
+error: this returns a `Result<_, ()>`
   --> $DIR/result_unit_error.rs:12:5
    |
 LL |     fn get_that_error(&self) -> Result<bool, ()>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use a custom Error type instead
+   = help: use a custom `Error` type instead
 
-error: this returns a `Result<_, ()>
+error: this returns a `Result<_, ()>`
   --> $DIR/result_unit_error.rs:14:5
    |
 LL |     fn get_this_one_too(&self) -> Result<bool, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use a custom Error type instead
+   = help: use a custom `Error` type instead
 
-error: this returns a `Result<_, ()>
+error: this returns a `Result<_, ()>`
   --> $DIR/result_unit_error.rs:32:5
    |
 LL |     pub fn unit_error(&self) -> Result<usize, ()> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use a custom Error type instead
+   = help: use a custom `Error` type instead
 
-error: this returns a `Result<_, ()>
+error: this returns a `Result<_, ()>`
   --> $DIR/result_unit_error.rs:41:5
    |
 LL |     pub fn should_lint() -> ResInv<(), usize> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use a custom Error type instead
+   = help: use a custom `Error` type instead
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/same_item_push.rs b/tests/ui/same_item_push.rs
index a37c8782ec3..9d420ec672a 100644
--- a/tests/ui/same_item_push.rs
+++ b/tests/ui/same_item_push.rs
@@ -148,4 +148,11 @@ fn main() {
         };
         vec.push(item);
     }
+
+    // Fix #6987
+    let mut vec = Vec::new();
+    for _ in 0..10 {
+        vec.push(1);
+        vec.extend(&[2]);
+    }
 }
diff --git a/tests/ui/stable_sort_primitive.fixed b/tests/ui/stable_sort_primitive.fixed
index 8f8f5665931..f5f18169df2 100644
--- a/tests/ui/stable_sort_primitive.fixed
+++ b/tests/ui/stable_sort_primitive.fixed
@@ -20,7 +20,7 @@ fn main() {
     // Negative examples: behavior changes if made unstable
     let mut vec = vec![1, 3, 2];
     vec.sort_by_key(|i| i / 2);
-    vec.sort_by(|a, b| (a + b).cmp(&b));
+    vec.sort_by(|&a, &b| (a + b).cmp(&b));
     // negative examples - Not of a primitive type
     let mut vec_of_complex = vec![String::from("hello"), String::from("world!")];
     vec_of_complex.sort();
diff --git a/tests/ui/stable_sort_primitive.rs b/tests/ui/stable_sort_primitive.rs
index f9bd9779067..8149c5638e0 100644
--- a/tests/ui/stable_sort_primitive.rs
+++ b/tests/ui/stable_sort_primitive.rs
@@ -20,7 +20,7 @@ fn main() {
     // Negative examples: behavior changes if made unstable
     let mut vec = vec![1, 3, 2];
     vec.sort_by_key(|i| i / 2);
-    vec.sort_by(|a, b| (a + b).cmp(&b));
+    vec.sort_by(|&a, &b| (a + b).cmp(&b));
     // negative examples - Not of a primitive type
     let mut vec_of_complex = vec![String::from("hello"), String::from("world!")];
     vec_of_complex.sort();
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/complex_types.rs b/tests/ui/type_complexity.rs
index 383bbb49dbe..383bbb49dbe 100644
--- a/tests/ui/complex_types.rs
+++ b/tests/ui/type_complexity.rs
diff --git a/tests/ui/complex_types.stderr b/tests/ui/type_complexity.stderr
index 7fcbb4bce88..7879233fdf2 100644
--- a/tests/ui/complex_types.stderr
+++ b/tests/ui/type_complexity.stderr
@@ -1,5 +1,5 @@
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:7:12
+  --> $DIR/type_complexity.rs:7:12
    |
 LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,85 +7,85 @@ LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    = note: `-D clippy::type-complexity` implied by `-D warnings`
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:8:12
+  --> $DIR/type_complexity.rs:8:12
    |
 LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:11:8
+  --> $DIR/type_complexity.rs:11:8
    |
 LL |     f: Vec<Vec<Box<(u32, u32, u32, u32)>>>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:14:11
+  --> $DIR/type_complexity.rs:14:11
    |
 LL | struct Ts(Vec<Vec<Box<(u32, u32, u32, u32)>>>);
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:17:11
+  --> $DIR/type_complexity.rs:17:11
    |
 LL |     Tuple(Vec<Vec<Box<(u32, u32, u32, u32)>>>),
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:18:17
+  --> $DIR/type_complexity.rs:18:17
    |
 LL |     Struct { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> },
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:22:14
+  --> $DIR/type_complexity.rs:22:14
    |
 LL |     const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:23:30
+  --> $DIR/type_complexity.rs:23:30
    |
 LL |     fn impl_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:27:14
+  --> $DIR/type_complexity.rs:27:14
    |
 LL |     const A: Vec<Vec<Box<(u32, u32, u32, u32)>>>;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:28:14
+  --> $DIR/type_complexity.rs:28:14
    |
 LL |     type B = Vec<Vec<Box<(u32, u32, u32, u32)>>>;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:29:25
+  --> $DIR/type_complexity.rs:29:25
    |
 LL |     fn method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:30:29
+  --> $DIR/type_complexity.rs:30:29
    |
 LL |     fn def_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:33:15
+  --> $DIR/type_complexity.rs:33:15
    |
 LL | fn test1() -> Vec<Vec<Box<(u32, u32, u32, u32)>>> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:37:14
+  --> $DIR/type_complexity.rs:37:14
    |
 LL | fn test2(_x: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> $DIR/complex_types.rs:40:13
+  --> $DIR/type_complexity.rs:40:13
    |
 LL |     let _y: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/upper_case_acronyms.rs b/tests/ui/upper_case_acronyms.rs
index 8c09c6f5b23..48bb9e54b12 100644
--- a/tests/ui/upper_case_acronyms.rs
+++ b/tests/ui/upper_case_acronyms.rs
@@ -24,4 +24,18 @@ struct GCCLLVMSomething;
 pub struct NOWARNINGHERE;
 pub struct ALSONoWarningHERE;
 
+// enum variants should not be linted if the num is pub
+pub enum ParseError<T> {
+    YDB(u8),
+    Utf8(std::string::FromUtf8Error),
+    Parse(T, String),
+}
+
+// private, do lint here
+enum ParseErrorPrivate<T> {
+    WASD(u8),
+    Utf8(std::string::FromUtf8Error),
+    Parse(T, String),
+}
+
 fn main() {}
diff --git a/tests/ui/upper_case_acronyms.stderr b/tests/ui/upper_case_acronyms.stderr
index bbe38991e52..250b196a99e 100644
--- a/tests/ui/upper_case_acronyms.stderr
+++ b/tests/ui/upper_case_acronyms.stderr
@@ -48,5 +48,11 @@ error: name `FIN` contains a capitalized acronym
 LL |     FIN,
    |     ^^^ help: consider making the acronym lowercase, except the initial letter: `Fin`
 
-error: aborting due to 8 previous errors
+error: name `WASD` contains a capitalized acronym
+  --> $DIR/upper_case_acronyms.rs:36:5
+   |
+LL |     WASD(u8),
+   |     ^^^^ help: consider making the acronym lowercase, except the initial letter: `Wasd`
+
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed
index 85677159620..da35f2e5c1b 100644
--- a/tests/ui/vec.fixed
+++ b/tests/ui/vec.fixed
@@ -6,9 +6,14 @@
 struct NonCopy;
 
 fn on_slice(_: &[u8]) {}
+
+fn on_mut_slice(_: &mut [u8]) {}
+
 #[allow(clippy::ptr_arg)]
 fn on_vec(_: &Vec<u8>) {}
 
+fn on_mut_vec(_: &mut Vec<u8>) {}
+
 struct Line {
     length: usize,
 }
@@ -22,28 +27,38 @@ impl Line {
 fn main() {
     on_slice(&[]);
     on_slice(&[]);
+    on_mut_slice(&mut []);
 
     on_slice(&[1, 2]);
     on_slice(&[1, 2]);
+    on_mut_slice(&mut [1, 2]);
 
     on_slice(&[1, 2]);
     on_slice(&[1, 2]);
+    on_mut_slice(&mut [1, 2]);
     #[rustfmt::skip]
     on_slice(&[1, 2]);
     on_slice(&[1, 2]);
+    on_mut_slice(&mut [1, 2]);
 
     on_slice(&[1; 2]);
     on_slice(&[1; 2]);
+    on_mut_slice(&mut [1; 2]);
 
     on_vec(&vec![]);
     on_vec(&vec![1, 2]);
     on_vec(&vec![1; 2]);
+    on_mut_vec(&mut vec![]);
+    on_mut_vec(&mut vec![1, 2]);
+    on_mut_vec(&mut vec![1; 2]);
 
     // Now with non-constant expressions
     let line = Line { length: 2 };
 
     on_slice(&vec![2; line.length]);
     on_slice(&vec![2; line.length()]);
+    on_mut_slice(&mut vec![2; line.length]);
+    on_mut_slice(&mut vec![2; line.length()]);
 
     for a in &[1, 2, 3] {
         println!("{:?}", a);
@@ -54,6 +69,7 @@ fn main() {
     }
 
     on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
+    on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
 
     // Ok
     for a in vec![1; 201] {
diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs
index 03b8ee81665..e9ed83e5c5a 100644
--- a/tests/ui/vec.rs
+++ b/tests/ui/vec.rs
@@ -6,9 +6,14 @@
 struct NonCopy;
 
 fn on_slice(_: &[u8]) {}
+
+fn on_mut_slice(_: &mut [u8]) {}
+
 #[allow(clippy::ptr_arg)]
 fn on_vec(_: &Vec<u8>) {}
 
+fn on_mut_vec(_: &mut Vec<u8>) {}
+
 struct Line {
     length: usize,
 }
@@ -22,28 +27,38 @@ impl Line {
 fn main() {
     on_slice(&vec![]);
     on_slice(&[]);
+    on_mut_slice(&mut vec![]);
 
     on_slice(&vec![1, 2]);
     on_slice(&[1, 2]);
+    on_mut_slice(&mut vec![1, 2]);
 
     on_slice(&vec![1, 2]);
     on_slice(&[1, 2]);
+    on_mut_slice(&mut vec![1, 2]);
     #[rustfmt::skip]
     on_slice(&vec!(1, 2));
     on_slice(&[1, 2]);
+    on_mut_slice(&mut vec![1, 2]);
 
     on_slice(&vec![1; 2]);
     on_slice(&[1; 2]);
+    on_mut_slice(&mut vec![1; 2]);
 
     on_vec(&vec![]);
     on_vec(&vec![1, 2]);
     on_vec(&vec![1; 2]);
+    on_mut_vec(&mut vec![]);
+    on_mut_vec(&mut vec![1, 2]);
+    on_mut_vec(&mut vec![1; 2]);
 
     // Now with non-constant expressions
     let line = Line { length: 2 };
 
     on_slice(&vec![2; line.length]);
     on_slice(&vec![2; line.length()]);
+    on_mut_slice(&mut vec![2; line.length]);
+    on_mut_slice(&mut vec![2; line.length()]);
 
     for a in vec![1, 2, 3] {
         println!("{:?}", a);
@@ -54,6 +69,7 @@ fn main() {
     }
 
     on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
+    on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
 
     // Ok
     for a in vec![1; 201] {
diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr
index 37e28ebddb5..7d1de05a5c8 100644
--- a/tests/ui/vec.stderr
+++ b/tests/ui/vec.stderr
@@ -1,5 +1,5 @@
 error: useless use of `vec!`
-  --> $DIR/vec.rs:23:14
+  --> $DIR/vec.rs:28:14
    |
 LL |     on_slice(&vec![]);
    |              ^^^^^^^ help: you can use a slice directly: `&[]`
@@ -7,34 +7,64 @@ LL |     on_slice(&vec![]);
    = note: `-D clippy::useless-vec` implied by `-D warnings`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:26:14
+  --> $DIR/vec.rs:30:18
+   |
+LL |     on_mut_slice(&mut vec![]);
+   |                  ^^^^^^^^^^^ help: you can use a slice directly: `&mut []`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:32:14
    |
 LL |     on_slice(&vec![1, 2]);
    |              ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:29:14
+  --> $DIR/vec.rs:34:18
+   |
+LL |     on_mut_slice(&mut vec![1, 2]);
+   |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:36:14
    |
 LL |     on_slice(&vec![1, 2]);
    |              ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:32:14
+  --> $DIR/vec.rs:38:18
+   |
+LL |     on_mut_slice(&mut vec![1, 2]);
+   |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:40:14
    |
 LL |     on_slice(&vec!(1, 2));
    |              ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:35:14
+  --> $DIR/vec.rs:42:18
+   |
+LL |     on_mut_slice(&mut vec![1, 2]);
+   |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:44:14
    |
 LL |     on_slice(&vec![1; 2]);
    |              ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:48:14
+  --> $DIR/vec.rs:46:18
+   |
+LL |     on_mut_slice(&mut vec![1; 2]);
+   |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:63:14
    |
 LL |     for a in vec![1, 2, 3] {
    |              ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]`
 
-error: aborting due to 6 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/vec_box_sized.fixed b/tests/ui/vec_box_sized.fixed
index 4fa28b525c3..a40d91fdb18 100644
--- a/tests/ui/vec_box_sized.fixed
+++ b/tests/ui/vec_box_sized.fixed
@@ -9,6 +9,8 @@ struct BigStruct([i32; 10000]);
 /// The following should trigger the lint
 mod should_trigger {
     use super::SizedStruct;
+    const C: Vec<i32> = Vec::new();
+    static S: Vec<i32> = Vec::new();
 
     struct StructWithVecBox {
         sized_type: Vec<SizedStruct>,
diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs
index 7dc735cd90b..843bbb64e71 100644
--- a/tests/ui/vec_box_sized.rs
+++ b/tests/ui/vec_box_sized.rs
@@ -9,6 +9,8 @@ struct BigStruct([i32; 10000]);
 /// The following should trigger the lint
 mod should_trigger {
     use super::SizedStruct;
+    const C: Vec<Box<i32>> = Vec::new();
+    static S: Vec<Box<i32>> = Vec::new();
 
     struct StructWithVecBox {
         sized_type: Vec<Box<SizedStruct>>,
diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr
index 83435a40aa1..c518267f041 100644
--- a/tests/ui/vec_box_sized.stderr
+++ b/tests/ui/vec_box_sized.stderr
@@ -1,28 +1,40 @@
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:14:21
+  --> $DIR/vec_box_sized.rs:12:14
    |
-LL |         sized_type: Vec<Box<SizedStruct>>,
-   |                     ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
+LL |     const C: Vec<Box<i32>> = Vec::new();
+   |              ^^^^^^^^^^^^^ help: try: `Vec<i32>`
    |
    = note: `-D clippy::vec-box` implied by `-D warnings`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:17:14
+  --> $DIR/vec_box_sized.rs:13:15
+   |
+LL |     static S: Vec<Box<i32>> = Vec::new();
+   |               ^^^^^^^^^^^^^ help: try: `Vec<i32>`
+
+error: `Vec<T>` is already on the heap, the boxing is unnecessary
+  --> $DIR/vec_box_sized.rs:16:21
+   |
+LL |         sized_type: Vec<Box<SizedStruct>>,
+   |                     ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
+
+error: `Vec<T>` is already on the heap, the boxing is unnecessary
+  --> $DIR/vec_box_sized.rs:19:14
    |
 LL |     struct A(Vec<Box<SizedStruct>>);
    |              ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:18:18
+  --> $DIR/vec_box_sized.rs:20:18
    |
 LL |     struct B(Vec<Vec<Box<(u32)>>>);
    |                  ^^^^^^^^^^^^^^^ help: try: `Vec<u32>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:46:23
+  --> $DIR/vec_box_sized.rs:48:23
    |
 LL |         pub fn f() -> Vec<Box<S>> {
    |                       ^^^^^^^^^^^ help: try: `Vec<S>`
 
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs
index ba9e19a1722..cdfbdb8b0db 100644
--- a/tests/ui/wrong_self_convention.rs
+++ b/tests/ui/wrong_self_convention.rs
@@ -165,15 +165,10 @@ mod issue6307 {
 }
 
 mod issue6727 {
-    trait ToU64 {
-        fn to_u64(self) -> u64;
-        fn to_u64_v2(&self) -> u64;
-    }
-
     #[derive(Clone, Copy)]
     struct FooCopy;
 
-    impl ToU64 for FooCopy {
+    impl FooCopy {
         fn to_u64(self) -> u64 {
             1
         }
@@ -185,7 +180,7 @@ mod issue6727 {
 
     struct FooNoCopy;
 
-    impl ToU64 for FooNoCopy {
+    impl FooNoCopy {
         // trigger lint
         fn to_u64(self) -> u64 {
             2
diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr
index 1d58a12ac79..29f5ba82695 100644
--- a/tests/ui/wrong_self_convention.stderr
+++ b/tests/ui/wrong_self_convention.stderr
@@ -176,7 +176,7 @@ LL |         fn from_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:181:22
+  --> $DIR/wrong_self_convention.rs:176:22
    |
 LL |         fn to_u64_v2(&self) -> u64 {
    |                      ^^^^^
@@ -184,7 +184,7 @@ LL |         fn to_u64_v2(&self) -> u64 {
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
-  --> $DIR/wrong_self_convention.rs:190:19
+  --> $DIR/wrong_self_convention.rs:185:19
    |
 LL |         fn to_u64(self) -> u64 {
    |                   ^^^^
diff --git a/tests/ui/wrong_self_convention2.rs b/tests/ui/wrong_self_convention2.rs
new file mode 100644
index 00000000000..8b42aa59e13
--- /dev/null
+++ b/tests/ui/wrong_self_convention2.rs
@@ -0,0 +1,32 @@
+// edition:2018
+#![warn(clippy::wrong_self_convention)]
+#![warn(clippy::wrong_pub_self_convention)]
+#![allow(dead_code)]
+
+fn main() {}
+
+mod issue6983 {
+    pub struct Thing;
+    pub trait Trait {
+        fn to_thing(&self) -> Thing;
+    }
+
+    impl Trait for u8 {
+        // don't trigger, e.g. `ToString` from `std` requires `&self`
+        fn to_thing(&self) -> Thing {
+            Thing
+        }
+    }
+
+    trait ToU64 {
+        fn to_u64(self) -> u64;
+    }
+
+    struct FooNoCopy;
+    // trigger lint
+    impl ToU64 for FooNoCopy {
+        fn to_u64(self) -> u64 {
+            2
+        }
+    }
+}
diff --git a/tests/ui/wrong_self_convention2.stderr b/tests/ui/wrong_self_convention2.stderr
new file mode 100644
index 00000000000..0ca1a390974
--- /dev/null
+++ b/tests/ui/wrong_self_convention2.stderr
@@ -0,0 +1,11 @@
+error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
+  --> $DIR/wrong_self_convention2.rs:28:19
+   |
+LL |         fn to_u64(self) -> u64 {
+   |                   ^^^^
+   |
+   = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
+   = help: consider choosing a less ambiguous name
+
+error: aborting due to previous error
+