summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/map_err_ignore.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/map_err_ignore.rs154
1 files changed, 0 insertions, 154 deletions
diff --git a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
deleted file mode 100644
index 21d0e19eb..000000000
--- a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
+++ /dev/null
@@ -1,154 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_hir::{CaptureBy, Closure, Expr, ExprKind, PatKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for instances of `map_err(|_| Some::Enum)`
- ///
- /// ### Why is this bad?
- /// This `map_err` throws away the original error rather than allowing the enum to contain and report the cause of the error
- ///
- /// ### Example
- /// Before:
- /// ```rust
- /// use std::fmt;
- ///
- /// #[derive(Debug)]
- /// enum Error {
- /// Indivisible,
- /// Remainder(u8),
- /// }
- ///
- /// impl fmt::Display for Error {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// match self {
- /// Error::Indivisible => write!(f, "could not divide input by three"),
- /// Error::Remainder(remainder) => write!(
- /// f,
- /// "input is not divisible by three, remainder = {}",
- /// remainder
- /// ),
- /// }
- /// }
- /// }
- ///
- /// impl std::error::Error for Error {}
- ///
- /// fn divisible_by_3(input: &str) -> Result<(), Error> {
- /// input
- /// .parse::<i32>()
- /// .map_err(|_| Error::Indivisible)
- /// .map(|v| v % 3)
- /// .and_then(|remainder| {
- /// if remainder == 0 {
- /// Ok(())
- /// } else {
- /// Err(Error::Remainder(remainder as u8))
- /// }
- /// })
- /// }
- /// ```
- ///
- /// After:
- /// ```rust
- /// use std::{fmt, num::ParseIntError};
- ///
- /// #[derive(Debug)]
- /// enum Error {
- /// Indivisible(ParseIntError),
- /// Remainder(u8),
- /// }
- ///
- /// impl fmt::Display for Error {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// match self {
- /// Error::Indivisible(_) => write!(f, "could not divide input by three"),
- /// Error::Remainder(remainder) => write!(
- /// f,
- /// "input is not divisible by three, remainder = {}",
- /// remainder
- /// ),
- /// }
- /// }
- /// }
- ///
- /// impl std::error::Error for Error {
- /// fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- /// match self {
- /// Error::Indivisible(source) => Some(source),
- /// _ => None,
- /// }
- /// }
- /// }
- ///
- /// fn divisible_by_3(input: &str) -> Result<(), Error> {
- /// input
- /// .parse::<i32>()
- /// .map_err(Error::Indivisible)
- /// .map(|v| v % 3)
- /// .and_then(|remainder| {
- /// if remainder == 0 {
- /// Ok(())
- /// } else {
- /// Err(Error::Remainder(remainder as u8))
- /// }
- /// })
- /// }
- /// ```
- #[clippy::version = "1.48.0"]
- pub MAP_ERR_IGNORE,
- restriction,
- "`map_err` should not ignore the original error"
-}
-
-declare_lint_pass!(MapErrIgnore => [MAP_ERR_IGNORE]);
-
-impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
- // do not try to lint if this is from a macro or desugaring
- fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) {
- if e.span.from_expansion() {
- return;
- }
-
- // check if this is a method call (e.g. x.foo())
- if let ExprKind::MethodCall(method, args, _) = e.kind {
- // only work if the method name is `map_err` and there are only 2 arguments (e.g. x.map_err(|_|[1]
- // Enum::Variant[2]))
- if method.ident.as_str() == "map_err" && args.len() == 2 {
- // make sure the first argument is a closure, and grab the CaptureRef, BodyId, and fn_decl_span
- // fields
- if let ExprKind::Closure(&Closure {
- capture_clause,
- body,
- fn_decl_span,
- ..
- }) = args[1].kind
- {
- // check if this is by Reference (meaning there's no move statement)
- if capture_clause == CaptureBy::Ref {
- // Get the closure body to check the parameters and values
- let closure_body = cx.tcx.hir().body(body);
- // make sure there's only one parameter (`|_|`)
- if closure_body.params.len() == 1 {
- // make sure that parameter is the wild token (`_`)
- if let PatKind::Wild = closure_body.params[0].pat.kind {
- // span the area of the closure capture and warn that the
- // original error will be thrown away
- span_lint_and_help(
- cx,
- MAP_ERR_IGNORE,
- fn_decl_span,
- "`map_err(|_|...` wildcard pattern discards the original error",
- None,
- "consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
- );
- }
- }
- }
- }
- }
- }
- }
-}