Auto merge of #11865 - yuxqiu:map_unwrap_or_default, r=Jarcho
feat: add `manual_is_variant_and` lint changelog: add a new lint [`manual_is_variant_and`]. - Replace `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` with `option.is_some_and(f)` and `result.is_ok_and(f)` where `f` is a function or closure that returns `bool`. - MSRV is set to 1.70.0 for this lint; when `is_some_and` and `is_ok_and` was stabilised --- For example, for the following code: ```rust let opt = Some(0); opt.map(|x| x > 1).unwrap_or_default(); ``` It suggests to instead write: ```rust let opt = Some(0); opt.is_some_and(|x| x > 1) ```
This commit is contained in:
commit
c6aeb28a7b
11 changed files with 290 additions and 6 deletions
51
tests/ui/manual_is_variant_and.fixed
Normal file
51
tests/ui/manual_is_variant_and.fixed
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//@aux-build:option_helpers.rs
|
||||
#![warn(clippy::manual_is_variant_and)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate option_helpers;
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn option_methods() {
|
||||
let opt = Some(1);
|
||||
|
||||
// Check for `option.map(_).unwrap_or_default()` use.
|
||||
// Single line case.
|
||||
let _ = opt.is_some_and(|x| x > 1);
|
||||
// Multi-line cases.
|
||||
let _ = opt.is_some_and(|x| {
|
||||
x > 1
|
||||
});
|
||||
let _ = opt.is_some_and(|x| x > 1);
|
||||
let _ = opt
|
||||
.is_some_and(|x| x > 1);
|
||||
|
||||
// won't fix because the return type of the closure is not `bool`
|
||||
let _ = opt.map(|x| x + 1).unwrap_or_default();
|
||||
|
||||
let opt2 = Some('a');
|
||||
let _ = opt2.is_some_and(char::is_alphanumeric); // should lint
|
||||
let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn result_methods() {
|
||||
let res: Result<i32, ()> = Ok(1);
|
||||
|
||||
// multi line cases
|
||||
let _ = res.is_ok_and(|x| {
|
||||
x > 1
|
||||
});
|
||||
let _ = res.is_ok_and(|x| x > 1);
|
||||
|
||||
// won't fix because the return type of the closure is not `bool`
|
||||
let _ = res.map(|x| x + 1).unwrap_or_default();
|
||||
|
||||
let res2: Result<char, ()> = Ok('a');
|
||||
let _ = res2.is_ok_and(char::is_alphanumeric); // should lint
|
||||
let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_methods();
|
||||
result_methods();
|
||||
}
|
||||
57
tests/ui/manual_is_variant_and.rs
Normal file
57
tests/ui/manual_is_variant_and.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//@aux-build:option_helpers.rs
|
||||
#![warn(clippy::manual_is_variant_and)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate option_helpers;
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn option_methods() {
|
||||
let opt = Some(1);
|
||||
|
||||
// Check for `option.map(_).unwrap_or_default()` use.
|
||||
// Single line case.
|
||||
let _ = opt.map(|x| x > 1)
|
||||
// Should lint even though this call is on a separate line.
|
||||
.unwrap_or_default();
|
||||
// Multi-line cases.
|
||||
let _ = opt.map(|x| {
|
||||
x > 1
|
||||
}
|
||||
).unwrap_or_default();
|
||||
let _ = opt.map(|x| x > 1).unwrap_or_default();
|
||||
let _ = opt
|
||||
.map(|x| x > 1)
|
||||
.unwrap_or_default();
|
||||
|
||||
// won't fix because the return type of the closure is not `bool`
|
||||
let _ = opt.map(|x| x + 1).unwrap_or_default();
|
||||
|
||||
let opt2 = Some('a');
|
||||
let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
|
||||
let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn result_methods() {
|
||||
let res: Result<i32, ()> = Ok(1);
|
||||
|
||||
// multi line cases
|
||||
let _ = res.map(|x| {
|
||||
x > 1
|
||||
}
|
||||
).unwrap_or_default();
|
||||
let _ = res.map(|x| x > 1)
|
||||
.unwrap_or_default();
|
||||
|
||||
// won't fix because the return type of the closure is not `bool`
|
||||
let _ = res.map(|x| x + 1).unwrap_or_default();
|
||||
|
||||
let res2: Result<char, ()> = Ok('a');
|
||||
let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
|
||||
let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_methods();
|
||||
result_methods();
|
||||
}
|
||||
82
tests/ui/manual_is_variant_and.stderr
Normal file
82
tests/ui/manual_is_variant_and.stderr
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:13:17
|
||||
|
|
||||
LL | let _ = opt.map(|x| x > 1)
|
||||
| _________________^
|
||||
LL | | // Should lint even though this call is on a separate line.
|
||||
LL | | .unwrap_or_default();
|
||||
| |____________________________^ help: use: `is_some_and(|x| x > 1)`
|
||||
|
|
||||
= note: `-D clippy::manual-is-variant-and` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::manual_is_variant_and)]`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:17:17
|
||||
|
|
||||
LL | let _ = opt.map(|x| {
|
||||
| _________________^
|
||||
LL | | x > 1
|
||||
LL | | }
|
||||
LL | | ).unwrap_or_default();
|
||||
| |_________________________^
|
||||
|
|
||||
help: use
|
||||
|
|
||||
LL ~ let _ = opt.is_some_and(|x| {
|
||||
LL + x > 1
|
||||
LL ~ });
|
||||
|
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:21:17
|
||||
|
|
||||
LL | let _ = opt.map(|x| x > 1).unwrap_or_default();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(|x| x > 1)`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:23:10
|
||||
|
|
||||
LL | .map(|x| x > 1)
|
||||
| __________^
|
||||
LL | | .unwrap_or_default();
|
||||
| |____________________________^ help: use: `is_some_and(|x| x > 1)`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:30:18
|
||||
|
|
||||
LL | let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(char::is_alphanumeric)`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on a `Result` value
|
||||
--> $DIR/manual_is_variant_and.rs:39:17
|
||||
|
|
||||
LL | let _ = res.map(|x| {
|
||||
| _________________^
|
||||
LL | | x > 1
|
||||
LL | | }
|
||||
LL | | ).unwrap_or_default();
|
||||
| |_________________________^
|
||||
|
|
||||
help: use
|
||||
|
|
||||
LL ~ let _ = res.is_ok_and(|x| {
|
||||
LL + x > 1
|
||||
LL ~ });
|
||||
|
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on a `Result` value
|
||||
--> $DIR/manual_is_variant_and.rs:43:17
|
||||
|
|
||||
LL | let _ = res.map(|x| x > 1)
|
||||
| _________________^
|
||||
LL | | .unwrap_or_default();
|
||||
| |____________________________^ help: use: `is_ok_and(|x| x > 1)`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on a `Result` value
|
||||
--> $DIR/manual_is_variant_and.rs:50:18
|
||||
|
|
||||
LL | let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_ok_and(char::is_alphanumeric)`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue