rust-clippy
rust-clippy copied to clipboard
Lint unused written length returned by `io::Write::write`
It's possible that this will cause partial write (depending on what W is), which may not be intended:
use std::io;
fn write_foo<W: io::Write>(w: &mut W) -> io::Result<()> {
w.write(b"foo")?;
Ok(())
}
This should be changed to either
fn write_foo<W: io::Write>(w: &mut W) -> io::Result<()> {
let written = w.write(b"foo")?;
// ... handle written
Ok(())
}
or
fn write_foo<W: io::Write>(w: &mut W) -> io::Result<()> {
w.write_all(b"foo")?;
Ok(())
}
I'm all for a general lint on expr; that has a type other than (). But your case is special, I think it even should be deny by default, since it's obviously a bug.
Unused result of Read::read should also be linted as well and suggest to use `read_exact".
To fully close this we probably need to use the dataflow analysis of MIR to prove that the write/read count is either used for a decision (to error or to retry, or is "used" good enough?) or escapes the function (by writing to a reference arg or by returning the value).
In case of escaping, the function needs to be marked so it is treated just like read/write. Since that is not feasible, we can require the function to have a #[io_amount_ret] or #[io_amount_ref(arg_name)] attribute that we collect when the lint is in check_crate and thus tread calls to that function just like read/write calls.
@oli-obk I think first approximation considering escaped value as used would be already very useful. I've witnessed multiple bugs that would be caught by that and don't remember ever seeing a bug that wouldn't. The only common escaping of the value is within Read/Write impl when delegating (self.0.read()) and since that is already considered in lint it's non-issue.
Oh, it's already implemented, I thought it wasn't because I hit a false negative: #9226. :sweat_smile: