blob: 6e0e2c5ea7202e4481b995ca74b11d9716b98414 [file] [log] [blame]
#![warn(clippy::if_same_then_else)]
#![allow(
clippy::disallowed_names,
clippy::eq_op,
clippy::never_loop,
clippy::no_effect,
clippy::unused_unit,
clippy::zero_divided_by_zero,
clippy::branches_sharing_code,
dead_code,
unreachable_code
)]
use std::ops::*;
struct Foo {
bar: u8,
}
fn foo() -> bool {
unimplemented!()
}
fn if_same_then_else() {
if true {
Foo { bar: 42 };
0..10;
..;
0..;
..10;
0..=10;
foo();
} else {
Foo { bar: 42 };
0..10;
..;
0..;
..10;
0..=10;
foo();
}
//~^^^^^^^^^^^^^^^^^ if_same_then_else
if true {
Foo { bar: 42 };
} else {
Foo { bar: 43 };
}
if true {
();
} else {
()
}
if true {
0..10;
} else {
0..=10;
}
if true {
foo();
foo();
} else {
foo();
}
let _ = if true { 0.0 } else { 0.0 };
//~^ if_same_then_else
let _ = if true { -0.0 } else { -0.0 };
//~^ if_same_then_else
let _ = if true { 0.0 } else { -0.0 };
// Different NaNs
let _ = if true { 0.0 / 0.0 } else { f32::NAN };
if true {
foo();
}
let _ = if true { 42 } else { 42 };
//~^ if_same_then_else
if true {
let bar = if true { 42 } else { 43 };
while foo() {
break;
}
bar + 1;
} else {
let bar = if true { 42 } else { 43 };
while foo() {
break;
}
bar + 1;
}
//~^^^^^^^^^^^^^^^ if_same_then_else
if true {
let _ = match 42 {
42 => 1,
a if a > 0 => 2,
10..=15 => 3,
_ => 4,
};
} else if false {
foo();
} else if foo() {
let _ = match 42 {
42 => 1,
a if a > 0 => 2,
10..=15 => 3,
_ => 4,
};
}
}
// Issue #2423. This was causing an ICE.
fn func() {
if true {
f(&[0; 62]);
f(&[0; 4]);
f(&[0; 3]);
} else {
f(&[0; 62]);
f(&[0; 6]);
f(&[0; 6]);
}
}
fn f(val: &[u8]) {}
mod issue_8836 {
fn do_not_lint() {
if true {
todo!()
} else {
todo!()
}
if true {
todo!();
} else {
todo!();
}
if true {
unimplemented!()
} else {
unimplemented!()
}
if true {
unimplemented!();
} else {
unimplemented!();
}
if true {
println!("FOO");
todo!();
} else {
println!("FOO");
todo!();
}
if true {
println!("FOO");
unimplemented!();
} else {
println!("FOO");
unimplemented!();
}
if true {
println!("FOO");
todo!()
} else {
println!("FOO");
todo!()
}
if true {
println!("FOO");
unimplemented!()
} else {
println!("FOO");
unimplemented!()
}
}
}
mod issue_11213 {
fn reproducer(x: bool) -> bool {
if x {
0_u8.is_power_of_two()
} else {
0_u16.is_power_of_two()
}
}
// a more obvious reproducer that shows
// why the code above is problematic:
fn v2(x: bool) -> bool {
trait Helper {
fn is_u8(&self) -> bool;
}
impl Helper for u8 {
fn is_u8(&self) -> bool {
true
}
}
impl Helper for u16 {
fn is_u8(&self) -> bool {
false
}
}
// this is certainly not the same code in both branches
// it returns a different bool depending on the branch.
if x { 0_u8.is_u8() } else { 0_u16.is_u8() }
}
fn do_lint(x: bool) -> bool {
// but do lint if the type of the literal is the same
if x {
0_u8.is_power_of_two()
} else {
0_u8.is_power_of_two()
}
//~^^^^^ if_same_then_else
}
}
fn main() {}
fn issue16416<T>(x: bool, a: T, b: T)
where
T: Add + Sub + Mul + Div + Rem + BitAnd + BitOr + BitXor + PartialEq + Eq + PartialOrd + Ord + Shr + Shl + Copy,
{
// Non-guaranteed-commutative operators
_ = if x { a * b } else { b * a };
_ = if x { a + b } else { b + a };
_ = if x { a - b } else { b - a };
_ = if x { a / b } else { b / a };
_ = if x { a % b } else { b % a };
_ = if x { a << b } else { b << a };
_ = if x { a >> b } else { b >> a };
_ = if x { a & b } else { b & a };
_ = if x { a ^ b } else { b ^ a };
_ = if x { a | b } else { b | a };
// Guaranteed commutative operators
//~v if_same_then_else
_ = if x { a == b } else { b == a };
//~v if_same_then_else
_ = if x { a != b } else { b != a };
// Symetric operators
//~v if_same_then_else
_ = if x { a < b } else { b > a };
//~v if_same_then_else
_ = if x { a <= b } else { b >= a };
//~v if_same_then_else
_ = if x { a > b } else { b < a };
//~v if_same_then_else
_ = if x { a >= b } else { b <= a };
}
fn issue16416_prim(x: bool, a: u32, b: u32) {
// Non-commutative operators
_ = if x { a - b } else { b - a };
_ = if x { a / b } else { b / a };
_ = if x { a % b } else { b % a };
_ = if x { a << b } else { b << a };
_ = if x { a >> b } else { b >> a };
// Commutative operators on primitive types
//~v if_same_then_else
_ = if x { a * b } else { b * a };
//~v if_same_then_else
_ = if x { a + b } else { b + a };
//~v if_same_then_else
_ = if x { a & b } else { b & a };
//~v if_same_then_else
_ = if x { a ^ b } else { b ^ a };
//~v if_same_then_else
_ = if x { a | b } else { b | a };
// Always commutative operators
//~v if_same_then_else
_ = if x { a == b } else { b == a };
//~v if_same_then_else
_ = if x { a != b } else { b != a };
// Symetric operators
//~v if_same_then_else
_ = if x { a < b } else { b > a };
//~v if_same_then_else
_ = if x { a <= b } else { b >= a };
//~v if_same_then_else
_ = if x { a > b } else { b < a };
//~v if_same_then_else
_ = if x { a >= b } else { b <= a };
}