Fixes #2426 (if_same_then_else false positive)

This commit is contained in:
Oliver Schneider 2018-02-09 15:23:51 +01:00
parent ff32d5f734
commit 6feb0dd982
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
4 changed files with 30 additions and 56 deletions

View file

@ -134,15 +134,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste {
/// Implementation of `IF_SAME_THEN_ELSE`. /// Implementation of `IF_SAME_THEN_ELSE`.
fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) { fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) {
let hash: &Fn(&&Block) -> u64 = &|block| -> u64 {
let mut h = SpanlessHash::new(cx);
h.hash_block(block);
h.finish()
};
let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) };
if let Some((i, j)) = search_same(blocks, hash, eq) { if let Some((i, j)) = search_same_sequenced(blocks, eq) {
span_note_and_lint( span_note_and_lint(
cx, cx,
IF_SAME_THEN_ELSE, IF_SAME_THEN_ELSE,
@ -309,6 +303,19 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
result result
} }
fn search_same_sequenced<T, Eq>(exprs: &[T], eq: Eq) -> Option<(&T, &T)>
where
Eq: Fn(&T, &T) -> bool,
{
for win in exprs.windows(2) {
if eq(&win[0], &win[1]) {
return Some((&win[0], &win[1]));
}
}
None
}
fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)> fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)>
where where
Hash: Fn(&T) -> u64, Hash: Fn(&T) -> u64,

View file

@ -0,0 +1,13 @@
#![deny(if_same_then_else)]
fn main() {}
pub fn foo(a: i32, b: i32) -> Option<&'static str> {
if a == b {
None
} else if a > b {
Some("a pfeil b")
} else {
None
}
}

View file

@ -160,7 +160,7 @@ fn if_same_then_else() -> Result<&'static str, ()> {
else if false { else if false {
foo(); foo();
} }
else if foo() { //~ ERROR same body as `if` block else if foo() {
let _ = match 42 { let _ = match 42 {
42 => 1, 42 => 1,
a if a > 0 => 2, a if a > 0 => 2,
@ -336,7 +336,7 @@ fn if_same_then_else() -> Result<&'static str, ()> {
let foo = "bar"; let foo = "bar";
return Ok(&foo[0..]); return Ok(&foo[0..]);
} }
else { //~ ERROR same body as `if` block else {
let foo = ""; let foo = "";
return Ok(&foo[0..]); return Ok(&foo[0..]);
} }

View file

@ -151,32 +151,6 @@ note: same as this
139 | | } 139 | | }
| |_____^ | |_____^
error: this `if` has identical blocks
--> $DIR/copies.rs:163:19
|
163 | else if foo() { //~ ERROR same body as `if` block
| ___________________^
164 | | let _ = match 42 {
165 | | 42 => 1,
166 | | a if a > 0 => 2,
... |
169 | | };
170 | | }
| |_____^
|
note: same as this
--> $DIR/copies.rs:152:13
|
152 | if true {
| _____________^
153 | | let _ = match 42 {
154 | | 42 => 1,
155 | | a if a > 0 => 2,
... |
158 | | };
159 | | }
| |_____^
error: this `if` has identical blocks error: this `if` has identical blocks
--> $DIR/copies.rs:175:10 --> $DIR/copies.rs:175:10
| |
@ -370,26 +344,6 @@ note: same as this
326 | | } 326 | | }
| |_____^ | |_____^
error: this `if` has identical blocks
--> $DIR/copies.rs:339:10
|
339 | else { //~ ERROR same body as `if` block
| __________^
340 | | let foo = "";
341 | | return Ok(&foo[0..]);
342 | | }
| |_____^
|
note: same as this
--> $DIR/copies.rs:331:13
|
331 | if true {
| _____________^
332 | | let foo = "";
333 | | return Ok(&foo[0..]);
334 | | }
| |_____^
error: this `if` has the same condition as a previous if error: this `if` has the same condition as a previous if
--> $DIR/copies.rs:353:13 --> $DIR/copies.rs:353:13
| |
@ -427,5 +381,5 @@ note: same as this
361 | if 2*a == 1 { 361 | if 2*a == 1 {
| ^^^^^^^^ | ^^^^^^^^
error: aborting due to 22 previous errors error: aborting due to 20 previous errors