summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/tests/ui/branches_sharing_code
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/tests/ui/branches_sharing_code')
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/false_positives.rs95
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs223
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr143
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs114
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr121
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs119
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr155
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs155
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr101
9 files changed, 1226 insertions, 0 deletions
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/false_positives.rs b/src/tools/clippy/tests/ui/branches_sharing_code/false_positives.rs
new file mode 100644
index 000000000..5e3a1a296
--- /dev/null
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/false_positives.rs
@@ -0,0 +1,95 @@
+#![allow(dead_code)]
+#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+
+use std::sync::Mutex;
+
+// ##################################
+// # Issue clippy#7369
+// ##################################
+#[derive(Debug)]
+pub struct FooBar {
+ foo: Vec<u32>,
+}
+
+impl FooBar {
+ pub fn bar(&mut self) {
+ if true {
+ self.foo.pop();
+ } else {
+ self.baz();
+
+ self.foo.pop();
+
+ self.baz()
+ }
+ }
+
+ fn baz(&mut self) {}
+}
+
+fn foo(x: u32, y: u32) -> u32 {
+ x / y
+}
+
+fn main() {
+ let x = (1, 2);
+ let _ = if true {
+ let (x, y) = x;
+ foo(x, y)
+ } else {
+ let (y, x) = x;
+ foo(x, y)
+ };
+
+ let m = Mutex::new(0u32);
+ let l = m.lock().unwrap();
+ let _ = if true {
+ drop(l);
+ println!("foo");
+ m.lock().unwrap();
+ 0
+ } else if *l == 0 {
+ drop(l);
+ println!("foo");
+ println!("bar");
+ m.lock().unwrap();
+ 1
+ } else {
+ drop(l);
+ println!("foo");
+ println!("baz");
+ m.lock().unwrap();
+ 2
+ };
+
+ if true {
+ let _guard = m.lock();
+ println!("foo");
+ } else {
+ println!("foo");
+ }
+
+ if true {
+ let _guard = m.lock();
+ println!("foo");
+ println!("bar");
+ } else {
+ let _guard = m.lock();
+ println!("foo");
+ println!("baz");
+ }
+
+ let mut c = 0;
+ for _ in 0..5 {
+ if c == 0 {
+ c += 1;
+ println!("0");
+ } else if c == 1 {
+ c += 1;
+ println!("1");
+ } else {
+ c += 1;
+ println!("more");
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs
new file mode 100644
index 000000000..12f550d9c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs
@@ -0,0 +1,223 @@
+#![allow(dead_code, clippy::equatable_if_let)]
+#![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 fp_if_let_issue7054() {
+ // This shouldn't trigger the lint
+ let string;
+ let _x = if let true = true {
+ ""
+ } else if true {
+ string = "x".to_owned();
+ &string
+ } else {
+ string = "y".to_owned();
+ &string
+ };
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr
new file mode 100644
index 000000000..5e1a68d21
--- /dev/null
+++ b/src/tools/clippy/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 these statements after the if
+ |
+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 these statements after the if
+ |
+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 these statements after the if
+ |
+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 these statements after the if
+ |
+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 these statements after the if
+ |
+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 these statements after the if
+ |
+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 these statements after the if
+ |
+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 these statements after the if
+ |
+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 these statements after the if
+ |
+LL ~ if x == 17 { b = 1; a = 0x99; } else { }
+LL + a = 0x99;
+ |
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs
new file mode 100644
index 000000000..bdeb0a395
--- /dev/null
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs
@@ -0,0 +1,114 @@
+#![allow(dead_code, clippy::mixed_read_write_in_expression)]
+#![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");
+ }
+}
+
+#[allow(clippy::vec_init_then_push)]
+fn pf_local_with_inferred_type_issue7053() {
+ if true {
+ let mut v = Vec::new();
+ v.push(0);
+ } else {
+ let mut v = Vec::new();
+ v.push("");
+ };
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr
new file mode 100644
index 000000000..d890b12ec
--- /dev/null
+++ b/src/tools/clippy/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 these statements before the if
+ |
+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 these statements before the if
+ |
+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 these statements before the if
+ |
+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 these statements before the if
+ |
+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 these statements before the if
+ |
+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 these statements before the if
+ |
+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/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
new file mode 100644
index 000000000..deefdad32
--- /dev/null
+++ b/src/tools/clippy/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/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
new file mode 100644
index 000000000..a270f637f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
@@ -0,0 +1,155 @@
+error: all if blocks contain the same code at both the start and the end
+ --> $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: this code is shared at the end
+ --> $DIR/shared_at_top_and_bottom.rs:28:5
+ |
+LL | / let _u = 9;
+LL | | }
+ | |_____^
+help: consider moving these statements before the if
+ |
+LL ~ let t = 7;
+LL + let _overlap_start = t * 2;
+LL + let _overlap_end = 2 * t;
+LL + if x == 7 {
+ |
+help: consider moving these statements after the if
+ |
+LL ~ }
+LL + let _u = 9;
+ |
+
+error: all if blocks contain the same code at both the start and the end
+ --> $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: this code is shared 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 these statements before the if
+ |
+LL ~ let r = 7;
+LL + let _overlap_start = r;
+LL + let _overlap_middle = r * r;
+LL + if x == 99 {
+ |
+help: consider moving these statements after the if
+ |
+LL ~ }
+LL + let _overlap_end = r * r * r;
+LL + let z = "end";
+ |
+
+error: all if blocks contain the same code at both the start and the end
+ --> $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: this code is shared 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 these statements before the if
+ |
+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: consider moving these statements after the if
+ |
+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 + };
+LL + process_data(pack);
+ |
+
+error: all if blocks contain the same code at both the start and the end
+ --> $DIR/shared_at_top_and_bottom.rs:94:5
+ |
+LL | / let _ = if x == 7 {
+LL | | let _ = 19;
+ | |___________________^
+ |
+note: this code is shared 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 these statements before the if
+ |
+LL ~ let _ = 19;
+LL + let _ = if x == 7 {
+ |
+help: consider moving these statements after the if
+ |
+LL ~ }
+LL ~ x << 2;
+ |
+
+error: all if blocks contain the same code at both the start and the end
+ --> $DIR/shared_at_top_and_bottom.rs:106:5
+ |
+LL | / if x == 9 {
+LL | | let _ = 17;
+ | |___________________^
+ |
+note: this code is shared 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 these statements before the if
+ |
+LL ~ let _ = 17;
+LL + if x == 9 {
+ |
+help: consider moving these statements after the if
+ |
+LL ~ }
+LL + x * 4
+ |
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs
new file mode 100644
index 000000000..a26141be2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs
@@ -0,0 +1,155 @@
+#![allow(dead_code, clippy::mixed_read_write_in_expression)]
+#![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/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr
new file mode 100644
index 000000000..a815995e7
--- /dev/null
+++ b/src/tools/clippy/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
+