Add manual_filter lint for Option
Share much of its implementation with `manual_map` and should greatly benefit from its previous feedback.
This commit is contained in:
parent
18e10ca290
commit
0958f9486b
13 changed files with 951 additions and 67 deletions
119
tests/ui/manual_filter.fixed
Normal file
119
tests/ui/manual_filter.fixed
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::manual_filter)]
|
||||
#![allow(unused_variables, dead_code)]
|
||||
|
||||
fn main() {
|
||||
Some(0).filter(|&x| x <= 0);
|
||||
|
||||
Some(1).filter(|&x| x <= 0);
|
||||
|
||||
Some(2).filter(|&x| x <= 0);
|
||||
|
||||
Some(3).filter(|&x| x > 0);
|
||||
|
||||
let y = Some(4);
|
||||
y.filter(|&x| x <= 0);
|
||||
|
||||
Some(5).filter(|&x| x > 0);
|
||||
|
||||
Some(6).as_ref().filter(|&x| x > &0);
|
||||
|
||||
let external_cond = true;
|
||||
Some(String::new()).filter(|x| external_cond);
|
||||
|
||||
Some(7).filter(|&x| external_cond);
|
||||
|
||||
Some(8).filter(|&x| x != 0);
|
||||
|
||||
Some(9).filter(|&x| x > 10 && x < 100);
|
||||
|
||||
const fn f1() {
|
||||
// Don't lint, `.filter` is not const
|
||||
match Some(10) {
|
||||
Some(x) => {
|
||||
if x > 10 && x < 100 {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(clippy::blocks_in_if_conditions)]
|
||||
Some(11).filter(|&x| {
|
||||
println!("foo");
|
||||
x > 10 && x < 100
|
||||
});
|
||||
|
||||
match Some(12) {
|
||||
// Don't Lint, statement is lost by `.filter`
|
||||
Some(x) => {
|
||||
if x > 10 && x < 100 {
|
||||
println!("foo");
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
match Some(13) {
|
||||
// Don't Lint, because of `None => Some(1)`
|
||||
Some(x) => {
|
||||
if x > 10 && x < 100 {
|
||||
println!("foo");
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => Some(1),
|
||||
};
|
||||
|
||||
unsafe fn f(x: u32) -> bool {
|
||||
true
|
||||
}
|
||||
let _ = Some(14).filter(|&x| unsafe { f(x) });
|
||||
let _ = Some(15).filter(|&x| unsafe { f(x) });
|
||||
|
||||
#[allow(clippy::redundant_pattern_matching)]
|
||||
if let Some(_) = Some(16) {
|
||||
Some(16)
|
||||
} else { Some(16).filter(|&x| x % 2 == 0) };
|
||||
|
||||
match Some((17, 17)) {
|
||||
// Not linted for now could be
|
||||
Some((x, y)) => {
|
||||
if y != x {
|
||||
Some((x, y))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
struct NamedTuple {
|
||||
pub x: u8,
|
||||
pub y: (i32, u32),
|
||||
}
|
||||
|
||||
match Some(NamedTuple {
|
||||
// Not linted for now could be
|
||||
x: 17,
|
||||
y: (18, 19),
|
||||
}) {
|
||||
Some(NamedTuple { x, y }) => {
|
||||
if y.1 != x as u32 {
|
||||
Some(NamedTuple { x, y })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
}
|
||||
243
tests/ui/manual_filter.rs
Normal file
243
tests/ui/manual_filter.rs
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::manual_filter)]
|
||||
#![allow(unused_variables, dead_code)]
|
||||
|
||||
fn main() {
|
||||
match Some(0) {
|
||||
None => None,
|
||||
Some(x) => {
|
||||
if x > 0 {
|
||||
None
|
||||
} else {
|
||||
Some(x)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
match Some(1) {
|
||||
Some(x) => {
|
||||
if x > 0 {
|
||||
None
|
||||
} else {
|
||||
Some(x)
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
match Some(2) {
|
||||
Some(x) => {
|
||||
if x > 0 {
|
||||
None
|
||||
} else {
|
||||
Some(x)
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
match Some(3) {
|
||||
Some(x) => {
|
||||
if x > 0 {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
let y = Some(4);
|
||||
match y {
|
||||
// Some(4)
|
||||
None => None,
|
||||
Some(x) => {
|
||||
if x > 0 {
|
||||
None
|
||||
} else {
|
||||
Some(x)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
match Some(5) {
|
||||
Some(x) => {
|
||||
if x > 0 {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
match Some(6) {
|
||||
Some(ref x) => {
|
||||
if x > &0 {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let external_cond = true;
|
||||
match Some(String::new()) {
|
||||
Some(x) => {
|
||||
if external_cond {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(x) = Some(7) {
|
||||
if external_cond { Some(x) } else { None }
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match &Some(8) {
|
||||
&Some(x) => {
|
||||
if x != 0 {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
match Some(9) {
|
||||
Some(x) => {
|
||||
if x > 10 && x < 100 {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
const fn f1() {
|
||||
// Don't lint, `.filter` is not const
|
||||
match Some(10) {
|
||||
Some(x) => {
|
||||
if x > 10 && x < 100 {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(clippy::blocks_in_if_conditions)]
|
||||
match Some(11) {
|
||||
// Lint, statement is preserved by `.filter`
|
||||
Some(x) => {
|
||||
if {
|
||||
println!("foo");
|
||||
x > 10 && x < 100
|
||||
} {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
match Some(12) {
|
||||
// Don't Lint, statement is lost by `.filter`
|
||||
Some(x) => {
|
||||
if x > 10 && x < 100 {
|
||||
println!("foo");
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
match Some(13) {
|
||||
// Don't Lint, because of `None => Some(1)`
|
||||
Some(x) => {
|
||||
if x > 10 && x < 100 {
|
||||
println!("foo");
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => Some(1),
|
||||
};
|
||||
|
||||
unsafe fn f(x: u32) -> bool {
|
||||
true
|
||||
}
|
||||
let _ = match Some(14) {
|
||||
Some(x) => {
|
||||
if unsafe { f(x) } {
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
let _ = match Some(15) {
|
||||
Some(x) => unsafe {
|
||||
if f(x) { Some(x) } else { None }
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
#[allow(clippy::redundant_pattern_matching)]
|
||||
if let Some(_) = Some(16) {
|
||||
Some(16)
|
||||
} else if let Some(x) = Some(16) {
|
||||
// Lint starting from here
|
||||
if x % 2 == 0 { Some(x) } else { None }
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match Some((17, 17)) {
|
||||
// Not linted for now could be
|
||||
Some((x, y)) => {
|
||||
if y != x {
|
||||
Some((x, y))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
struct NamedTuple {
|
||||
pub x: u8,
|
||||
pub y: (i32, u32),
|
||||
}
|
||||
|
||||
match Some(NamedTuple {
|
||||
// Not linted for now could be
|
||||
x: 17,
|
||||
y: (18, 19),
|
||||
}) {
|
||||
Some(NamedTuple { x, y }) => {
|
||||
if y.1 != x as u32 {
|
||||
Some(NamedTuple { x, y })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
}
|
||||
191
tests/ui/manual_filter.stderr
Normal file
191
tests/ui/manual_filter.stderr
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:7:5
|
||||
|
|
||||
LL | / match Some(0) {
|
||||
LL | | None => None,
|
||||
LL | | Some(x) => {
|
||||
LL | | if x > 0 {
|
||||
... |
|
||||
LL | | },
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(0).filter(|&x| x <= 0)`
|
||||
|
|
||||
= note: `-D clippy::manual-filter` implied by `-D warnings`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:18:5
|
||||
|
|
||||
LL | / match Some(1) {
|
||||
LL | | Some(x) => {
|
||||
LL | | if x > 0 {
|
||||
LL | | None
|
||||
... |
|
||||
LL | | None => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(1).filter(|&x| x <= 0)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:29:5
|
||||
|
|
||||
LL | / match Some(2) {
|
||||
LL | | Some(x) => {
|
||||
LL | | if x > 0 {
|
||||
LL | | None
|
||||
... |
|
||||
LL | | _ => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(2).filter(|&x| x <= 0)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:40:5
|
||||
|
|
||||
LL | / match Some(3) {
|
||||
LL | | Some(x) => {
|
||||
LL | | if x > 0 {
|
||||
LL | | Some(x)
|
||||
... |
|
||||
LL | | None => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(3).filter(|&x| x > 0)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:52:5
|
||||
|
|
||||
LL | / match y {
|
||||
LL | | // Some(4)
|
||||
LL | | None => None,
|
||||
LL | | Some(x) => {
|
||||
... |
|
||||
LL | | },
|
||||
LL | | };
|
||||
| |_____^ help: try this: `y.filter(|&x| x <= 0)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:64:5
|
||||
|
|
||||
LL | / match Some(5) {
|
||||
LL | | Some(x) => {
|
||||
LL | | if x > 0 {
|
||||
LL | | Some(x)
|
||||
... |
|
||||
LL | | _ => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(5).filter(|&x| x > 0)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:75:5
|
||||
|
|
||||
LL | / match Some(6) {
|
||||
LL | | Some(ref x) => {
|
||||
LL | | if x > &0 {
|
||||
LL | | Some(x)
|
||||
... |
|
||||
LL | | _ => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(6).as_ref().filter(|&x| x > &0)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:87:5
|
||||
|
|
||||
LL | / match Some(String::new()) {
|
||||
LL | | Some(x) => {
|
||||
LL | | if external_cond {
|
||||
LL | | Some(x)
|
||||
... |
|
||||
LL | | _ => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(String::new()).filter(|x| external_cond)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:98:5
|
||||
|
|
||||
LL | / if let Some(x) = Some(7) {
|
||||
LL | | if external_cond { Some(x) } else { None }
|
||||
LL | | } else {
|
||||
LL | | None
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(7).filter(|&x| external_cond)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:104:5
|
||||
|
|
||||
LL | / match &Some(8) {
|
||||
LL | | &Some(x) => {
|
||||
LL | | if x != 0 {
|
||||
LL | | Some(x)
|
||||
... |
|
||||
LL | | _ => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(8).filter(|&x| x != 0)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:115:5
|
||||
|
|
||||
LL | / match Some(9) {
|
||||
LL | | Some(x) => {
|
||||
LL | | if x > 10 && x < 100 {
|
||||
LL | | Some(x)
|
||||
... |
|
||||
LL | | None => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(9).filter(|&x| x > 10 && x < 100)`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:141:5
|
||||
|
|
||||
LL | / match Some(11) {
|
||||
LL | | // Lint, statement is preserved by `.filter`
|
||||
LL | | Some(x) => {
|
||||
LL | | if {
|
||||
... |
|
||||
LL | | None => None,
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
help: try this
|
||||
|
|
||||
LL ~ Some(11).filter(|&x| {
|
||||
LL + println!("foo");
|
||||
LL + x > 10 && x < 100
|
||||
LL ~ });
|
||||
|
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:185:13
|
||||
|
|
||||
LL | let _ = match Some(14) {
|
||||
| _____________^
|
||||
LL | | Some(x) => {
|
||||
LL | | if unsafe { f(x) } {
|
||||
LL | | Some(x)
|
||||
... |
|
||||
LL | | None => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(14).filter(|&x| unsafe { f(x) })`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:195:13
|
||||
|
|
||||
LL | let _ = match Some(15) {
|
||||
| _____________^
|
||||
LL | | Some(x) => unsafe {
|
||||
LL | | if f(x) { Some(x) } else { None }
|
||||
LL | | },
|
||||
LL | | None => None,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Some(15).filter(|&x| unsafe { f(x) })`
|
||||
|
||||
error: manual implementation of `Option::filter`
|
||||
--> $DIR/manual_filter.rs:205:12
|
||||
|
|
||||
LL | } else if let Some(x) = Some(16) {
|
||||
| ____________^
|
||||
LL | | // Lint starting from here
|
||||
LL | | if x % 2 == 0 { Some(x) } else { None }
|
||||
LL | | } else {
|
||||
LL | | None
|
||||
LL | | };
|
||||
| |_____^ help: try this: `{ Some(16).filter(|&x| x % 2 == 0) }`
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue