Skip to content

Commit

Permalink
add detection unused_io_amount of "or", "or_else" and "ok"
Browse files Browse the repository at this point in the history
  • Loading branch information
ABouttefeux committed Apr 22, 2021
1 parent 28dbcd8 commit 5625d58
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
20 changes: 15 additions & 5 deletions clippy_lints/src/unused_io_amount.rs
Expand Up @@ -47,25 +47,35 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
func.kind,
hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _))
) {
check_method_call(cx, &args[0], expr);
check_map_error(cx, &args[0], expr);
}
} else {
check_method_call(cx, res, expr);
check_map_error(cx, res, expr);
}
},

hir::ExprKind::MethodCall(path, _, args, _) => match &*path.ident.as_str() {
"expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
check_method_call(cx, &args[0], expr);
check_map_error(cx, &args[0], expr);
},
_ => (),
},

_ => (),
}
}
}

fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
let mut call = call;
while let hir::ExprKind::MethodCall(ref path, _, ref args, _) = call.kind {
if matches!(&*path.ident.as_str(), "or" | "or_else" | "ok") {
call = &args[0];
} else {
break;
}
}
check_method_call(cx, call, expr);
}

fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
if let hir::ExprKind::MethodCall(path, _, _, _) = call.kind {
let symbol = &*path.ident.as_str();
Expand Down
41 changes: 40 additions & 1 deletion tests/ui/unused_io_amount.rs
@@ -1,7 +1,7 @@
#![allow(dead_code)]
#![warn(clippy::unused_io_amount)]

use std::io;
use std::io::{self, Read};

fn question_mark<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> {
s.write(b"test")?;
Expand All @@ -22,4 +22,43 @@ fn vectored<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> {
Ok(())
}

fn ok(file: &str) -> Option<()> {
let mut reader = std::fs::File::open(file).ok()?;
let mut result = [0u8; 0];
reader.read(&mut result).ok()?;
Some(())
}

#[allow(clippy::redundant_closure)]
#[allow(clippy::bind_instead_of_map)]
fn or_else(file: &str) -> io::Result<()> {
let mut reader = std::fs::File::open(file)?;
let mut result = [0u8; 0];
reader.read(&mut result).or_else(|err| Err(err))?;
Ok(())
}

#[derive(Debug)]
enum Error {
Kind,
}

fn or(file: &str) -> Result<(), Error> {
let mut reader = std::fs::File::open(file).unwrap();
let mut result = [0u8; 0];
reader.read(&mut result).or(Err(Error::Kind))?;
Ok(())
}

fn combine_or(file: &str) -> Result<(), Error> {
let mut reader = std::fs::File::open(file).unwrap();
let mut result = [0u8; 0];
reader
.read(&mut result)
.or(Err(Error::Kind))
.or(Err(Error::Kind))
.expect("error");
Ok(())
}

fn main() {}
30 changes: 29 additions & 1 deletion tests/ui/unused_io_amount.stderr
Expand Up @@ -36,5 +36,33 @@ error: written amount is not handled
LL | s.write_vectored(&[io::IoSlice::new(&[])])?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 6 previous errors
error: read amount is not handled. Use `Read::read_exact` instead
--> $DIR/unused_io_amount.rs:28:5
|
LL | reader.read(&mut result).ok()?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: read amount is not handled. Use `Read::read_exact` instead
--> $DIR/unused_io_amount.rs:37:5
|
LL | reader.read(&mut result).or_else(|err| Err(err))?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: read amount is not handled. Use `Read::read_exact` instead
--> $DIR/unused_io_amount.rs:49:5
|
LL | reader.read(&mut result).or(Err(Error::Kind))?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: read amount is not handled. Use `Read::read_exact` instead
--> $DIR/unused_io_amount.rs:56:5
|
LL | / reader
LL | | .read(&mut result)
LL | | .or(Err(Error::Kind))
LL | | .or(Err(Error::Kind))
LL | | .expect("error");
| |________________________^

error: aborting due to 10 previous errors

0 comments on commit 5625d58

Please sign in to comment.