diff options
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.rs | 154 |
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| ...`)", - ); - } - } - } - } - } - } - } -} |