X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=clippy_lints%2Fsrc%2Funused_io_amount.rs;h=9990052e114b1f1e08426c0a88a98c0abd1801f4;hb=9f6b5de7deaf4dc9e7917370ad09ab85dc23997c;hp=43f980c72c4cf44553e565dce86f6637e5940076;hpb=6cba3da727f8e084c5124c77901b7ffba2264076;p=rust.git diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 43f980c72c4..9990052e114 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,73 +1,60 @@ -// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_try, match_trait_method, paths}; +use rustc_hir as hir; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; -use rustc::hir; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; - -/// **What it does:** Checks for unused written/read amount. -/// -/// **Why is this bad?** `io::Write::write` and `io::Read::read` are not -/// guaranteed to -/// process the entire buffer. They return how many bytes were processed, which -/// might be smaller -/// than a given buffer's length. If you don't need to deal with -/// partial-write/read, use -/// `write_all`/`read_exact` instead. -/// -/// **Known problems:** Detects only common patterns. -/// -/// **Example:** -/// ```rust,ignore -/// use std::io; -/// fn foo(w: &mut W) -> io::Result<()> { -/// // must be `w.write_all(b"foo")?;` -/// w.write(b"foo")?; -/// Ok(()) -/// } -/// ``` declare_clippy_lint! { + /// **What it does:** Checks for unused written/read amount. + /// + /// **Why is this bad?** `io::Write::write(_vectored)` and + /// `io::Read::read(_vectored)` are not guaranteed to + /// process the entire buffer. They return how many bytes were processed, which + /// might be smaller + /// than a given buffer's length. If you don't need to deal with + /// partial-write/read, use + /// `write_all`/`read_exact` instead. + /// + /// **Known problems:** Detects only common patterns. + /// + /// **Example:** + /// ```rust,ignore + /// use std::io; + /// fn foo(w: &mut W) -> io::Result<()> { + /// // must be `w.write_all(b"foo")?;` + /// w.write(b"foo")?; + /// Ok(()) + /// } + /// ``` pub UNUSED_IO_AMOUNT, correctness, "unused written/read amount" } -pub struct UnusedIoAmount; - -impl LintPass for UnusedIoAmount { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_IO_AMOUNT) - } -} +declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { - fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) { - let expr = match s.node { - hir::StmtKind::Semi(ref expr, _) | hir::StmtKind::Expr(ref expr, _) => &**expr, +impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { + fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { + let expr = match s.kind { + hir::StmtKind::Semi(ref expr) | hir::StmtKind::Expr(ref expr) => &**expr, _ => return, }; - match expr.node { + match expr.kind { hir::ExprKind::Match(ref res, _, _) if is_try(expr).is_some() => { - if let hir::ExprKind::Call(ref func, ref args) = res.node { - if let hir::ExprKind::Path(ref path) = func.node { - if match_qpath(path, &paths::TRY_INTO_RESULT) && args.len() == 1 { - check_method_call(cx, &args[0], expr); - } + if let hir::ExprKind::Call(ref func, ref args) = res.kind { + if matches!( + func.kind, + hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _)) + ) { + check_method_call(cx, &args[0], expr); } } else { check_method_call(cx, res, expr); } }, - hir::ExprKind::MethodCall(ref path, _, ref args) => match &*path.ident.as_str() { + hir::ExprKind::MethodCall(ref path, _, ref args, _) => match &*path.ident.as_str() { "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { check_method_call(cx, &args[0], expr); }, @@ -79,23 +66,28 @@ fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) { } } -fn check_method_call(cx: &LateContext<'_, '_>, call: &hir::Expr, expr: &hir::Expr) { - if let hir::ExprKind::MethodCall(ref path, _, _) = call.node { +fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) { + if let hir::ExprKind::MethodCall(ref path, _, _, _) = call.kind { let symbol = &*path.ident.as_str(); - if match_trait_method(cx, call, &paths::IO_READ) && symbol == "read" { - span_lint( + let read_trait = match_trait_method(cx, call, &paths::IO_READ); + let write_trait = match_trait_method(cx, call, &paths::IO_WRITE); + + match (read_trait, write_trait, symbol) { + (true, _, "read") => span_lint( cx, UNUSED_IO_AMOUNT, expr.span, - "handle read amount returned or use `Read::read_exact` instead", - ); - } else if match_trait_method(cx, call, &paths::IO_WRITE) && symbol == "write" { - span_lint( + "read amount is not handled. Use `Read::read_exact` instead", + ), + (true, _, "read_vectored") => span_lint(cx, UNUSED_IO_AMOUNT, expr.span, "read amount is not handled"), + (_, true, "write") => span_lint( cx, UNUSED_IO_AMOUNT, expr.span, - "handle written amount returned or use `Write::write_all` instead", - ); + "written amount is not handled. Use `Write::write_all` instead", + ), + (_, true, "write_vectored") => span_lint(cx, UNUSED_IO_AMOUNT, expr.span, "written amount is not handled"), + _ => (), } } }