1
- use crate :: utils:: span_lint_and_sugg ;
2
- use rustc_errors :: Applicability ;
3
- use rustc_hir:: { CaptureBy , Expr , ExprKind , PatKind , QPath } ;
1
+ use crate :: utils:: span_lint_and_help ;
2
+
3
+ use rustc_hir:: { CaptureBy , Expr , ExprKind , PatKind } ;
4
4
use rustc_lint:: { LateContext , LateLintPass } ;
5
5
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
6
6
@@ -12,33 +12,58 @@ declare_clippy_lint! {
12
12
/// **Known problems:** None.
13
13
///
14
14
/// **Example:**
15
- ///
15
+ /// Before:
16
16
/// ```rust
17
+ /// use std::convert::TryFrom;
18
+ ///
19
+ /// #[derive(Debug)]
17
20
/// enum Errors {
18
- /// Ignore
19
- ///}
20
- ///fn main() -> Result<(), Errors> {
21
+ /// Ignored
22
+ /// }
21
23
///
22
- /// let x = u32::try_from(-123_i32);
24
+ /// fn divisible_by_3(inp: i32) -> Result<u32, Errors> {
25
+ /// let i = u32::try_from(inp).map_err(|_| Errors::Ignored)?;
23
26
///
24
- /// println!("{:?}", x.map_err(|_| Errors::Ignore));
27
+ /// Ok(i)
28
+ /// }
29
+ /// ```
25
30
///
26
- /// Ok(())
27
- ///}
28
- /// ```
29
- /// Use instead:
30
- /// ```rust
31
- /// enum Errors {
32
- /// WithContext(TryFromIntError)
33
- ///}
34
- ///fn main() -> Result<(), Errors> {
31
+ /// After:
32
+ /// ```rust
33
+ /// use std::convert::TryFrom;
34
+ /// use std::num::TryFromIntError;
35
+ /// use std::fmt;
36
+ /// use std::error::Error;
37
+ ///
38
+ /// #[derive(Debug)]
39
+ /// enum ParseError {
40
+ /// Indivisible {
41
+ /// source: TryFromIntError,
42
+ /// input: String,
43
+ /// }
44
+ /// }
45
+ ///
46
+ /// impl fmt::Display for ParseError {
47
+ /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48
+ /// match &self {
49
+ /// ParseError::Indivisible{source: _, input} => write!(f, "Error: {}", input)
50
+ /// }
51
+ /// }
52
+ /// }
53
+ ///
54
+ /// impl Error for ParseError {}
35
55
///
36
- /// let x = u32::try_from(-123_i32);
56
+ /// impl ParseError {
57
+ /// fn new(source: TryFromIntError, input: String) -> ParseError {
58
+ /// ParseError::Indivisible{source, input}
59
+ /// }
60
+ /// }
37
61
///
38
- /// println!("{:?}", x.map_err(|e| Errors::WithContext(e)));
62
+ /// fn divisible_by_3(inp: i32) -> Result<u32, ParseError> {
63
+ /// let i = u32::try_from(inp).map_err(|e| ParseError::new(e, e.to_string()))?;
39
64
///
40
- /// Ok(() )
41
- ///}
65
+ /// Ok(i )
66
+ /// }
42
67
/// ```
43
68
pub MAP_ERR_IGNORE ,
44
69
style,
@@ -69,44 +94,16 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
69
94
if closure_body. params . len ( ) == 1 {
70
95
// make sure that parameter is the wild token (`_`)
71
96
if let PatKind :: Wild = closure_body. params [ 0 ] . pat . kind {
72
- // Check the value of the closure to see if we can build the enum we are throwing away
73
- // the error for make sure this is a Path
74
- if let ExprKind :: Path ( q_path) = & closure_body. value . kind {
75
- // this should be a resolved path, only keep the path field
76
- if let QPath :: Resolved ( _, path) = q_path {
77
- // finally get the idents for each path segment collect them as a string and
78
- // join them with the path separator ("::"")
79
- let closure_fold: String = path
80
- . segments
81
- . iter ( )
82
- . map ( |x| x. ident . as_str ( ) . to_string ( ) )
83
- . collect :: < Vec < String > > ( )
84
- . join ( "::" ) ;
85
- //Span the body of the closure (the |...| bit) and suggest the fix by taking
86
- // the error and encapsulating it in the enum
87
- span_lint_and_sugg (
88
- cx,
89
- MAP_ERR_IGNORE ,
90
- body_span,
91
- "`map_err` has thrown away the original error" ,
92
- "Allow the error enum to encapsulate the original error" ,
93
- format ! ( "|e| {}(e)" , closure_fold) ,
94
- Applicability :: HasPlaceholders ,
95
- ) ;
96
- }
97
- } else {
98
- //If we cannot build the enum in a human readable way just suggest not throwing way
99
- // the error
100
- span_lint_and_sugg (
101
- cx,
102
- MAP_ERR_IGNORE ,
103
- body_span,
104
- "`map_err` has thrown away the original error" ,
105
- "Allow the error enum to encapsulate the original error" ,
106
- "|e|" . to_string ( ) ,
107
- Applicability :: HasPlaceholders ,
108
- ) ;
109
- }
97
+ // span the area of the closure capture and warn that the
98
+ // original error will be thrown away
99
+ span_lint_and_help (
100
+ cx,
101
+ MAP_ERR_IGNORE ,
102
+ body_span,
103
+ "`map_else(|_|...` ignores the original error" ,
104
+ None ,
105
+ "Consider wrapping the error in an enum variant" ,
106
+ ) ;
110
107
}
111
108
}
112
109
}
0 commit comments