Auto merge of #10534 - samueltardieu:lines-filter-map-ok, r=llogiq
Flag `bufreader.lines().filter_map(Result::ok)` as suspicious This lint detects a problem that happened recently in https://github.com/uutils/coreutils and is described in https://github.com/rust-lang/rust/issues/64144. changelog: [`lines_filter_map_ok`]: new lint
This commit is contained in:
commit
ac4838c554
8 changed files with 215 additions and 0 deletions
29
tests/ui/lines_filter_map_ok.fixed
Normal file
29
tests/ui/lines_filter_map_ok.fixed
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused, clippy::map_identity)]
|
||||
#![warn(clippy::lines_filter_map_ok)]
|
||||
|
||||
use std::io::{self, BufRead, BufReader};
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let f = std::fs::File::open("/")?;
|
||||
// Lint
|
||||
BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ());
|
||||
// Lint
|
||||
let f = std::fs::File::open("/")?;
|
||||
BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ());
|
||||
let s = "foo\nbar\nbaz\n";
|
||||
// Lint
|
||||
io::stdin().lines().map_while(Result::ok).for_each(|_| ());
|
||||
// Lint
|
||||
io::stdin().lines().map_while(Result::ok).for_each(|_| ());
|
||||
// Do not lint (not a `Lines` iterator)
|
||||
io::stdin()
|
||||
.lines()
|
||||
.map(std::convert::identity)
|
||||
.filter_map(|x| x.ok())
|
||||
.for_each(|_| ());
|
||||
// Do not lint (not a `Result::ok()` extractor)
|
||||
io::stdin().lines().filter_map(|x| x.err()).for_each(|_| ());
|
||||
Ok(())
|
||||
}
|
||||
29
tests/ui/lines_filter_map_ok.rs
Normal file
29
tests/ui/lines_filter_map_ok.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused, clippy::map_identity)]
|
||||
#![warn(clippy::lines_filter_map_ok)]
|
||||
|
||||
use std::io::{self, BufRead, BufReader};
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let f = std::fs::File::open("/")?;
|
||||
// Lint
|
||||
BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ());
|
||||
// Lint
|
||||
let f = std::fs::File::open("/")?;
|
||||
BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ());
|
||||
let s = "foo\nbar\nbaz\n";
|
||||
// Lint
|
||||
io::stdin().lines().filter_map(Result::ok).for_each(|_| ());
|
||||
// Lint
|
||||
io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ());
|
||||
// Do not lint (not a `Lines` iterator)
|
||||
io::stdin()
|
||||
.lines()
|
||||
.map(std::convert::identity)
|
||||
.filter_map(|x| x.ok())
|
||||
.for_each(|_| ());
|
||||
// Do not lint (not a `Result::ok()` extractor)
|
||||
io::stdin().lines().filter_map(|x| x.err()).for_each(|_| ());
|
||||
Ok(())
|
||||
}
|
||||
51
tests/ui/lines_filter_map_ok.stderr
Normal file
51
tests/ui/lines_filter_map_ok.stderr
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
error: `filter_map()` will run forever if the iterator repeatedly produces an `Err`
|
||||
--> $DIR/lines_filter_map_ok.rs:11:31
|
||||
|
|
||||
LL | BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)`
|
||||
|
|
||||
note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
|
||||
--> $DIR/lines_filter_map_ok.rs:11:5
|
||||
|
|
||||
LL | BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `-D clippy::lines-filter-map-ok` implied by `-D warnings`
|
||||
|
||||
error: `flat_map()` will run forever if the iterator repeatedly produces an `Err`
|
||||
--> $DIR/lines_filter_map_ok.rs:14:31
|
||||
|
|
||||
LL | BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ());
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)`
|
||||
|
|
||||
note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
|
||||
--> $DIR/lines_filter_map_ok.rs:14:5
|
||||
|
|
||||
LL | BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `filter_map()` will run forever if the iterator repeatedly produces an `Err`
|
||||
--> $DIR/lines_filter_map_ok.rs:17:25
|
||||
|
|
||||
LL | io::stdin().lines().filter_map(Result::ok).for_each(|_| ());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)`
|
||||
|
|
||||
note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
|
||||
--> $DIR/lines_filter_map_ok.rs:17:5
|
||||
|
|
||||
LL | io::stdin().lines().filter_map(Result::ok).for_each(|_| ());
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `filter_map()` will run forever if the iterator repeatedly produces an `Err`
|
||||
--> $DIR/lines_filter_map_ok.rs:19:25
|
||||
|
|
||||
LL | io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)`
|
||||
|
|
||||
note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
|
||||
--> $DIR/lines_filter_map_ok.rs:19:5
|
||||
|
|
||||
LL | io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ());
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue