mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 15:11:30 +00:00
unused_io_amount
captures Ok(_)
s
Partial rewrite of `unused_io_account` to lint over Ok(_). Moved the check to `check_block` to simplify context checking for expressions and allow us to check only some expressions. For match (expr, arms) we emit a lint for io ops used on `expr` when an arm is `Ok(_)`. Also considers the cases when there are guards in the arms. It also captures `if let Ok(_) = ...` cases. For `Ok(_)` it emits a note indicating where the value is ignored. changelog: False Negatives [`unused_io_amount`]: Extended `unused_io_amount` to catch `Ok(_)`s in `If let` and match exprs.
This commit is contained in:
parent
a71211d0b5
commit
f73879e096
3 changed files with 406 additions and 126 deletions
|
@ -1,9 +1,10 @@
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::{is_trait_method, is_try, match_trait_method, paths};
|
use clippy_utils::{is_res_lang_ctor, is_trait_method, match_trait_method, paths};
|
||||||
|
use hir::{ExprKind, PatKind};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
use rustc_span::sym;
|
use rustc_span::{sym, Span};
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
|
@ -45,126 +46,219 @@ declare_clippy_lint! {
|
||||||
|
|
||||||
declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]);
|
declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
|
#[derive(Copy, Clone)]
|
||||||
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
|
enum IoOp {
|
||||||
let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = s.kind else {
|
AsyncWrite(bool),
|
||||||
return;
|
AsyncRead(bool),
|
||||||
};
|
SyncRead(bool),
|
||||||
|
SyncWrite(bool),
|
||||||
|
}
|
||||||
|
|
||||||
match expr.kind {
|
impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
|
||||||
hir::ExprKind::Match(res, _, _) if is_try(cx, expr).is_some() => {
|
/// We perform the check on the block level.
|
||||||
if let hir::ExprKind::Call(func, [ref arg_0, ..]) = res.kind {
|
/// If we want to catch match and if expressions that act as returns of the block
|
||||||
if matches!(
|
/// we need to check them at `check_expr` or `check_block` as they are not stmts
|
||||||
func.kind,
|
/// but we can't check them at `check_expr` because we need the broader context
|
||||||
hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..))
|
/// because we should do this only for the final expression of the block, and not for
|
||||||
) {
|
/// `StmtKind::Local` which binds values => the io amount is used.
|
||||||
check_map_error(cx, arg_0, expr);
|
///
|
||||||
}
|
/// To check for unused io amount in stmts, we only consider `StmtKind::Semi`.
|
||||||
} else {
|
/// `StmtKind::Local` is not considered because it binds values => the io amount is used.
|
||||||
check_map_error(cx, res, expr);
|
/// `StmtKind::Expr` is not considered because requires unit type => the io amount is used.
|
||||||
}
|
/// `StmtKind::Item` is not considered because it's not an expression.
|
||||||
},
|
///
|
||||||
hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() {
|
/// We then check the individual expressions via `check_expr`. We use the same logic for
|
||||||
"expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" | "is_ok" | "is_err" => {
|
/// semi expressions and the final expression as we need to check match and if expressions
|
||||||
check_map_error(cx, arg_0, expr);
|
/// for binding of the io amount to `Ok(_)`.
|
||||||
},
|
///
|
||||||
_ => (),
|
/// We explicitly check for the match source to be Normal as it needs special logic
|
||||||
},
|
/// to consider the arms, and we want to avoid breaking the logic for situations where things
|
||||||
_ => (),
|
/// get desugared to match.
|
||||||
|
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'tcx>) {
|
||||||
|
for stmt in block.stmts {
|
||||||
|
if let hir::StmtKind::Semi(exp) = stmt.kind {
|
||||||
|
check_expr(cx, exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(exp) = block.expr
|
||||||
|
&& matches!(exp.kind, hir::ExprKind::If(_, _, _) | hir::ExprKind::Match(_, _, _))
|
||||||
|
{
|
||||||
|
check_expr(cx, exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) {
|
||||||
|
match expr.kind {
|
||||||
|
hir::ExprKind::If(cond, _, _)
|
||||||
|
if let ExprKind::Let(hir::Let { pat, init, .. }) = cond.kind
|
||||||
|
&& pattern_is_ignored_ok(cx, pat)
|
||||||
|
&& let Some(op) = should_lint(cx, init) =>
|
||||||
|
{
|
||||||
|
emit_lint(cx, cond.span, op, &[pat.span]);
|
||||||
|
},
|
||||||
|
hir::ExprKind::Match(expr, arms, hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => {
|
||||||
|
let found_arms: Vec<_> = arms
|
||||||
|
.iter()
|
||||||
|
.filter_map(|arm| {
|
||||||
|
if pattern_is_ignored_ok(cx, arm.pat) {
|
||||||
|
Some(arm.span)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
if !found_arms.is_empty() {
|
||||||
|
emit_lint(cx, expr.span, op, found_arms.as_slice());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ if let Some(op) = should_lint(cx, expr) => {
|
||||||
|
emit_lint(cx, expr.span, op, &[]);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_lint<'a>(cx: &LateContext<'a>, mut inner: &'a hir::Expr<'a>) -> Option<IoOp> {
|
||||||
|
inner = unpack_match(inner);
|
||||||
|
inner = unpack_try(inner);
|
||||||
|
inner = unpack_call_chain(inner);
|
||||||
|
inner = unpack_await(inner);
|
||||||
|
// we type-check it to get whether it's a read/write or their vectorized forms
|
||||||
|
// and keep only the ones that are produce io amount
|
||||||
|
check_io_mode(cx, inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pattern_is_ignored_ok(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> bool {
|
||||||
|
// the if checks whether we are in a result Ok( ) pattern
|
||||||
|
// and the return checks whether it is unhandled
|
||||||
|
|
||||||
|
if let PatKind::TupleStruct(ref path, inner_pat, ddp) = pat.kind
|
||||||
|
// we check against Result::Ok to avoid linting on Err(_) or something else.
|
||||||
|
&& is_res_lang_ctor(cx, cx.qpath_res(path, pat.hir_id), hir::LangItem::ResultOk)
|
||||||
|
{
|
||||||
|
return match (inner_pat, ddp.as_opt_usize()) {
|
||||||
|
// Ok(_) pattern
|
||||||
|
([inner_pat], None) if matches!(inner_pat.kind, PatKind::Wild) => true,
|
||||||
|
// Ok(..) pattern
|
||||||
|
([], Some(0)) => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||||
|
while let hir::ExprKind::MethodCall(path, receiver, ..) = expr.kind {
|
||||||
|
if matches!(
|
||||||
|
path.ident.as_str(),
|
||||||
|
"unwrap" | "expect" | "unwrap_or" | "unwrap_or_else" | "ok" | "is_ok" | "is_err" | "or_else" | "or"
|
||||||
|
) {
|
||||||
|
expr = receiver;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||||
|
while let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind
|
||||||
|
&& matches!(
|
||||||
|
func.kind,
|
||||||
|
hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
expr = arg_0;
|
||||||
|
}
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||||
|
while let hir::ExprKind::Match(res, _, _) = expr.kind {
|
||||||
|
expr = res;
|
||||||
|
}
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
|
||||||
/// If `expr` is an (e).await, return the inner expression "e" that's being
|
/// If `expr` is an (e).await, return the inner expression "e" that's being
|
||||||
/// waited on. Otherwise return None.
|
/// waited on. Otherwise return None.
|
||||||
fn try_remove_await<'a>(expr: &'a hir::Expr<'a>) -> Option<&hir::Expr<'a>> {
|
fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> {
|
||||||
if let hir::ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind {
|
if let hir::ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind {
|
||||||
if let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind {
|
if let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind {
|
||||||
if matches!(
|
if matches!(
|
||||||
func.kind,
|
func.kind,
|
||||||
hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
|
hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
|
||||||
) {
|
) {
|
||||||
return Some(arg_0);
|
return arg_0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expr
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
|
/// Check whether the current expr is a function call for an IO operation
|
||||||
let mut call = call;
|
fn check_io_mode(cx: &LateContext<'_>, call: &hir::Expr<'_>) -> Option<IoOp> {
|
||||||
while let hir::ExprKind::MethodCall(path, receiver, ..) = call.kind {
|
let hir::ExprKind::MethodCall(path, ..) = call.kind else {
|
||||||
if matches!(path.ident.as_str(), "or" | "or_else" | "ok") {
|
return None;
|
||||||
call = receiver;
|
};
|
||||||
} else {
|
|
||||||
break;
|
let vectorized = match path.ident.as_str() {
|
||||||
|
"write_vectored" | "read_vectored" => true,
|
||||||
|
"write" | "read" => false,
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
match (
|
||||||
|
is_trait_method(cx, call, sym::IoRead),
|
||||||
|
is_trait_method(cx, call, sym::IoWrite),
|
||||||
|
match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
|
||||||
|
|| match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCREADEXT),
|
||||||
|
match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCWRITEEXT)
|
||||||
|
|| match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCWRITEEXT),
|
||||||
|
) {
|
||||||
|
(true, _, _, _) => Some(IoOp::SyncRead(vectorized)),
|
||||||
|
(_, true, _, _) => Some(IoOp::SyncWrite(vectorized)),
|
||||||
|
(_, _, true, _) => Some(IoOp::AsyncRead(vectorized)),
|
||||||
|
(_, _, _, true) => Some(IoOp::AsyncWrite(vectorized)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_lint(cx: &LateContext<'_>, span: Span, op: IoOp, wild_cards: &[Span]) {
|
||||||
|
let (msg, help) = match op {
|
||||||
|
IoOp::AsyncRead(false) => (
|
||||||
|
"read amount is not handled",
|
||||||
|
Some("use `AsyncReadExt::read_exact` instead, or handle partial reads"),
|
||||||
|
),
|
||||||
|
IoOp::SyncRead(false) => (
|
||||||
|
"read amount is not handled",
|
||||||
|
Some("use `Read::read_exact` instead, or handle partial reads"),
|
||||||
|
),
|
||||||
|
IoOp::SyncWrite(false) => (
|
||||||
|
"written amount is not handled",
|
||||||
|
Some("use `Write::write_all` instead, or handle partial writes"),
|
||||||
|
),
|
||||||
|
IoOp::AsyncWrite(false) => (
|
||||||
|
"written amount is not handled",
|
||||||
|
Some("use `AsyncWriteExt::write_all` instead, or handle partial writes"),
|
||||||
|
),
|
||||||
|
IoOp::SyncRead(true) | IoOp::AsyncRead(true) => ("read amount is not handled", None),
|
||||||
|
IoOp::SyncWrite(true) | IoOp::AsyncWrite(true) => ("written amount is not handled", None),
|
||||||
|
};
|
||||||
|
|
||||||
|
span_lint_and_then(cx, UNUSED_IO_AMOUNT, span, msg, |diag| {
|
||||||
|
if let Some(help_str) = help {
|
||||||
|
diag.help(help_str);
|
||||||
}
|
}
|
||||||
}
|
for span in wild_cards {
|
||||||
|
diag.span_note(
|
||||||
if let Some(call) = try_remove_await(call) {
|
*span,
|
||||||
check_method_call(cx, call, expr, true);
|
"the result is consumed here, but the amount of I/O bytes remains unhandled",
|
||||||
} else {
|
);
|
||||||
check_method_call(cx, call, expr, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>, is_await: bool) {
|
|
||||||
if let hir::ExprKind::MethodCall(path, ..) = call.kind {
|
|
||||||
let symbol = path.ident.as_str();
|
|
||||||
let read_trait = if is_await {
|
|
||||||
match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
|
|
||||||
|| match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCREADEXT)
|
|
||||||
} else {
|
|
||||||
is_trait_method(cx, call, sym::IoRead)
|
|
||||||
};
|
|
||||||
let write_trait = if is_await {
|
|
||||||
match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCWRITEEXT)
|
|
||||||
|| match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCWRITEEXT)
|
|
||||||
} else {
|
|
||||||
is_trait_method(cx, call, sym::IoWrite)
|
|
||||||
};
|
|
||||||
|
|
||||||
match (read_trait, write_trait, symbol, is_await) {
|
|
||||||
(true, _, "read", false) => span_lint_and_help(
|
|
||||||
cx,
|
|
||||||
UNUSED_IO_AMOUNT,
|
|
||||||
expr.span,
|
|
||||||
"read amount is not handled",
|
|
||||||
None,
|
|
||||||
"use `Read::read_exact` instead, or handle partial reads",
|
|
||||||
),
|
|
||||||
(true, _, "read", true) => span_lint_and_help(
|
|
||||||
cx,
|
|
||||||
UNUSED_IO_AMOUNT,
|
|
||||||
expr.span,
|
|
||||||
"read amount is not handled",
|
|
||||||
None,
|
|
||||||
"use `AsyncReadExt::read_exact` instead, or handle partial reads",
|
|
||||||
),
|
|
||||||
(true, _, "read_vectored", _) => {
|
|
||||||
span_lint(cx, UNUSED_IO_AMOUNT, expr.span, "read amount is not handled");
|
|
||||||
},
|
|
||||||
(_, true, "write", false) => span_lint_and_help(
|
|
||||||
cx,
|
|
||||||
UNUSED_IO_AMOUNT,
|
|
||||||
expr.span,
|
|
||||||
"written amount is not handled",
|
|
||||||
None,
|
|
||||||
"use `Write::write_all` instead, or handle partial writes",
|
|
||||||
),
|
|
||||||
(_, true, "write", true) => span_lint_and_help(
|
|
||||||
cx,
|
|
||||||
UNUSED_IO_AMOUNT,
|
|
||||||
expr.span,
|
|
||||||
"written amount is not handled",
|
|
||||||
None,
|
|
||||||
"use `AsyncWriteExt::write_all` instead, or handle partial writes",
|
|
||||||
),
|
|
||||||
(_, true, "write_vectored", _) => {
|
|
||||||
span_lint(cx, UNUSED_IO_AMOUNT, expr.span, "written amount is not handled");
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![allow(dead_code, clippy::needless_pass_by_ref_mut)]
|
#![allow(dead_code, clippy::needless_pass_by_ref_mut)]
|
||||||
|
#![allow(clippy::redundant_pattern_matching)]
|
||||||
#![warn(clippy::unused_io_amount)]
|
#![warn(clippy::unused_io_amount)]
|
||||||
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
|
@ -142,4 +143,90 @@ async fn undetected_bad_async_write<W: AsyncWrite + Unpin>(w: &mut W) {
|
||||||
future.await.unwrap();
|
future.await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn match_okay_underscore<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
match s.write(b"test") {
|
||||||
|
//~^ ERROR: written amount is not handled
|
||||||
|
Ok(_) => todo!(),
|
||||||
|
//~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
Err(_) => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
match s.read(&mut buf) {
|
||||||
|
//~^ ERROR: read amount is not handled
|
||||||
|
Ok(_) => todo!(),
|
||||||
|
//~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
Err(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_okay_underscore_read_expr<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
match s.read(&mut [0u8; 4]) {
|
||||||
|
//~^ ERROR: read amount is not handled
|
||||||
|
Ok(_) => todo!(),
|
||||||
|
//~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
Err(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_okay_underscore_write_expr<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
match s.write(b"test") {
|
||||||
|
//~^ ERROR: written amount is not handled
|
||||||
|
Ok(_) => todo!(),
|
||||||
|
//~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
Err(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn returned_value_should_not_lint<T: io::Read + io::Write>(s: &mut T) -> Result<usize, std::io::Error> {
|
||||||
|
s.write(b"test")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_okay_underscore_read_expr<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
if let Ok(_) = s.read(&mut [0u8; 4]) {
|
||||||
|
//~^ ERROR: read amount is not handled
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_okay_underscore_write_expr<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
if let Ok(_) = s.write(b"test") {
|
||||||
|
//~^ ERROR: written amount is not handled
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_okay_dots_write_expr<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
if let Ok(..) = s.write(b"test") {
|
||||||
|
//~^ ERROR: written amount is not handled
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_okay_underscore_write_expr_true_negative<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
if let Ok(bound) = s.write(b"test") {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_okay_underscore_true_neg<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
match s.write(b"test") {
|
||||||
|
Ok(bound) => todo!(),
|
||||||
|
Err(_) => todo!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn true_negative<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
let read_amount = s.read(&mut buf).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_return_should_not_raise<T: io::Read + io::Write>(s: &mut T) -> io::Result<usize> {
|
||||||
|
/// this is bad code because it goes around the problem of handling the read amount
|
||||||
|
/// by returning it, which makes it impossible to know this is a resonpose from the
|
||||||
|
/// correct account.
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
s.read(&mut buf)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:9:5
|
--> $DIR/unused_io_amount.rs:10:5
|
||||||
|
|
|
|
||||||
LL | s.write(b"test")?;
|
LL | s.write(b"test")?;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
@ -9,7 +9,7 @@ LL | s.write(b"test")?;
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::unused_io_amount)]`
|
= help: to override `-D warnings` add `#[allow(clippy::unused_io_amount)]`
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:12:5
|
--> $DIR/unused_io_amount.rs:13:5
|
||||||
|
|
|
|
||||||
LL | s.read(&mut buf)?;
|
LL | s.read(&mut buf)?;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
@ -17,7 +17,7 @@ LL | s.read(&mut buf)?;
|
||||||
= help: use `Read::read_exact` instead, or handle partial reads
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:18:5
|
--> $DIR/unused_io_amount.rs:19:5
|
||||||
|
|
|
|
||||||
LL | s.write(b"test").unwrap();
|
LL | s.write(b"test").unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -25,7 +25,7 @@ LL | s.write(b"test").unwrap();
|
||||||
= help: use `Write::write_all` instead, or handle partial writes
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:21:5
|
--> $DIR/unused_io_amount.rs:22:5
|
||||||
|
|
|
|
||||||
LL | s.read(&mut buf).unwrap();
|
LL | s.read(&mut buf).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -33,19 +33,19 @@ LL | s.read(&mut buf).unwrap();
|
||||||
= help: use `Read::read_exact` instead, or handle partial reads
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:26:5
|
--> $DIR/unused_io_amount.rs:27:5
|
||||||
|
|
|
|
||||||
LL | s.read_vectored(&mut [io::IoSliceMut::new(&mut [])])?;
|
LL | s.read_vectored(&mut [io::IoSliceMut::new(&mut [])])?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:28:5
|
--> $DIR/unused_io_amount.rs:29:5
|
||||||
|
|
|
|
||||||
LL | s.write_vectored(&[io::IoSlice::new(&[])])?;
|
LL | s.write_vectored(&[io::IoSlice::new(&[])])?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:36:5
|
--> $DIR/unused_io_amount.rs:37:5
|
||||||
|
|
|
|
||||||
LL | reader.read(&mut result).ok()?;
|
LL | reader.read(&mut result).ok()?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -53,7 +53,7 @@ LL | reader.read(&mut result).ok()?;
|
||||||
= help: use `Read::read_exact` instead, or handle partial reads
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:46:5
|
--> $DIR/unused_io_amount.rs:47:5
|
||||||
|
|
|
|
||||||
LL | reader.read(&mut result).or_else(|err| Err(err))?;
|
LL | reader.read(&mut result).or_else(|err| Err(err))?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -61,7 +61,7 @@ LL | reader.read(&mut result).or_else(|err| Err(err))?;
|
||||||
= help: use `Read::read_exact` instead, or handle partial reads
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:59:5
|
--> $DIR/unused_io_amount.rs:60:5
|
||||||
|
|
|
|
||||||
LL | reader.read(&mut result).or(Err(Error::Kind))?;
|
LL | reader.read(&mut result).or(Err(Error::Kind))?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -69,7 +69,7 @@ LL | reader.read(&mut result).or(Err(Error::Kind))?;
|
||||||
= help: use `Read::read_exact` instead, or handle partial reads
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:67:5
|
--> $DIR/unused_io_amount.rs:68:5
|
||||||
|
|
|
|
||||||
LL | / reader
|
LL | / reader
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -82,7 +82,7 @@ LL | | .expect("error");
|
||||||
= help: use `Read::read_exact` instead, or handle partial reads
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:77:5
|
--> $DIR/unused_io_amount.rs:78:5
|
||||||
|
|
|
|
||||||
LL | s.write(b"ok").is_ok();
|
LL | s.write(b"ok").is_ok();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -90,7 +90,7 @@ LL | s.write(b"ok").is_ok();
|
||||||
= help: use `Write::write_all` instead, or handle partial writes
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:79:5
|
--> $DIR/unused_io_amount.rs:80:5
|
||||||
|
|
|
|
||||||
LL | s.write(b"err").is_err();
|
LL | s.write(b"err").is_err();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -98,7 +98,7 @@ LL | s.write(b"err").is_err();
|
||||||
= help: use `Write::write_all` instead, or handle partial writes
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:82:5
|
--> $DIR/unused_io_amount.rs:83:5
|
||||||
|
|
|
|
||||||
LL | s.read(&mut buf).is_ok();
|
LL | s.read(&mut buf).is_ok();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -106,7 +106,7 @@ LL | s.read(&mut buf).is_ok();
|
||||||
= help: use `Read::read_exact` instead, or handle partial reads
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:84:5
|
--> $DIR/unused_io_amount.rs:85:5
|
||||||
|
|
|
|
||||||
LL | s.read(&mut buf).is_err();
|
LL | s.read(&mut buf).is_err();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -114,7 +114,7 @@ LL | s.read(&mut buf).is_err();
|
||||||
= help: use `Read::read_exact` instead, or handle partial reads
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:89:5
|
--> $DIR/unused_io_amount.rs:90:5
|
||||||
|
|
|
|
||||||
LL | w.write(b"hello world").await.unwrap();
|
LL | w.write(b"hello world").await.unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -122,7 +122,7 @@ LL | w.write(b"hello world").await.unwrap();
|
||||||
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:95:5
|
--> $DIR/unused_io_amount.rs:96:5
|
||||||
|
|
|
|
||||||
LL | r.read(&mut buf[..]).await.unwrap();
|
LL | r.read(&mut buf[..]).await.unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -130,7 +130,15 @@ LL | r.read(&mut buf[..]).await.unwrap();
|
||||||
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:109:9
|
--> $DIR/unused_io_amount.rs:104:5
|
||||||
|
|
|
||||||
|
LL | w.write(b"hello world");
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
|
error: written amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:110:9
|
||||||
|
|
|
|
||||||
LL | w.write(b"hello world").await?;
|
LL | w.write(b"hello world").await?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -138,7 +146,7 @@ LL | w.write(b"hello world").await?;
|
||||||
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:118:9
|
--> $DIR/unused_io_amount.rs:119:9
|
||||||
|
|
|
|
||||||
LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
|
LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -146,7 +154,7 @@ LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
|
||||||
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:127:5
|
--> $DIR/unused_io_amount.rs:128:5
|
||||||
|
|
|
|
||||||
LL | w.write(b"hello world").await.unwrap();
|
LL | w.write(b"hello world").await.unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -154,12 +162,103 @@ LL | w.write(b"hello world").await.unwrap();
|
||||||
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:133:5
|
--> $DIR/unused_io_amount.rs:134:5
|
||||||
|
|
|
|
||||||
LL | r.read(&mut buf[..]).await.unwrap();
|
LL | r.read(&mut buf[..]).await.unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: aborting due to 20 previous errors
|
error: written amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:147:11
|
||||||
|
|
|
||||||
|
LL | match s.write(b"test") {
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
note: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
--> $DIR/unused_io_amount.rs:149:9
|
||||||
|
|
|
||||||
|
LL | Ok(_) => todo!(),
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: read amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:155:11
|
||||||
|
|
|
||||||
|
LL | match s.read(&mut buf) {
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
note: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
--> $DIR/unused_io_amount.rs:157:9
|
||||||
|
|
|
||||||
|
LL | Ok(_) => todo!(),
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: read amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:164:11
|
||||||
|
|
|
||||||
|
LL | match s.read(&mut [0u8; 4]) {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
note: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
--> $DIR/unused_io_amount.rs:166:9
|
||||||
|
|
|
||||||
|
LL | Ok(_) => todo!(),
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: written amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:173:11
|
||||||
|
|
|
||||||
|
LL | match s.write(b"test") {
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
note: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
--> $DIR/unused_io_amount.rs:175:9
|
||||||
|
|
|
||||||
|
LL | Ok(_) => todo!(),
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: read amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:186:8
|
||||||
|
|
|
||||||
|
LL | if let Ok(_) = s.read(&mut [0u8; 4]) {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
note: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
--> $DIR/unused_io_amount.rs:186:12
|
||||||
|
|
|
||||||
|
LL | if let Ok(_) = s.read(&mut [0u8; 4]) {
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: written amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:193:8
|
||||||
|
|
|
||||||
|
LL | if let Ok(_) = s.write(b"test") {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
note: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
--> $DIR/unused_io_amount.rs:193:12
|
||||||
|
|
|
||||||
|
LL | if let Ok(_) = s.write(b"test") {
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: written amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:200:8
|
||||||
|
|
|
||||||
|
LL | if let Ok(..) = s.write(b"test") {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
note: the result is consumed here, but the amount of I/O bytes remains unhandled
|
||||||
|
--> $DIR/unused_io_amount.rs:200:12
|
||||||
|
|
|
||||||
|
LL | if let Ok(..) = s.write(b"test") {
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 28 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue