@@ -42,6 +42,9 @@ declare_clippy_lint! {
42
42
43
43
declare_lint_pass ! ( ImplicitReturn => [ IMPLICIT_RETURN ] ) ;
44
44
45
+ static LINT_BREAK : & str = "change `break` to `return` as shown" ;
46
+ static LINT_RETURN : & str = "add `return` as shown" ;
47
+
45
48
fn lint ( cx : & LateContext < ' _ , ' _ > , outer_span : Span , inner_span : Span , msg : & str ) {
46
49
let outer_span = span_to_outer_expn ( outer_span) ;
47
50
let inner_span = span_to_outer_expn ( inner_span) ;
@@ -66,12 +69,12 @@ fn span_to_outer_expn(span: Span) -> Span {
66
69
}
67
70
}
68
71
69
- fn expr_match ( cx : & LateContext < ' _ , ' _ > , expr : & Expr , ret_ty_is_never : bool ) {
72
+ fn expr_match ( cx : & LateContext < ' _ , ' _ > , expr : & Expr ) {
70
73
match & expr. node {
71
74
// loops could be using `break` instead of `return`
72
75
ExprKind :: Block ( block, ..) | ExprKind :: Loop ( block, ..) => {
73
76
if let Some ( expr) = & block. expr {
74
- expr_match ( cx, expr, ret_ty_is_never ) ;
77
+ expr_match ( cx, expr) ;
75
78
}
76
79
// only needed in the case of `break` with `;` at the end
77
80
else if let Some ( stmt) = block. stmts . last ( ) {
@@ -81,15 +84,15 @@ fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr, ret_ty_is_never: bool) {
81
84
if let ExprKind :: Break ( .., break_expr) = & expr. node;
82
85
if let Some ( break_expr) = break_expr;
83
86
then {
84
- lint( cx, expr. span, break_expr. span, "change `break` to `return` as shown" ) ;
87
+ lint( cx, expr. span, break_expr. span, LINT_BREAK ) ;
85
88
}
86
89
}
87
90
}
88
91
} ,
89
92
// use `return` instead of `break`
90
93
ExprKind :: Break ( .., break_expr) => {
91
94
if let Some ( break_expr) = break_expr {
92
- lint ( cx, expr. span , break_expr. span , "change `break` to `return` as shown" ) ;
95
+ lint ( cx, expr. span , break_expr. span , LINT_BREAK ) ;
93
96
}
94
97
} ,
95
98
ExprKind :: Match ( .., arms, source) => {
@@ -102,38 +105,29 @@ fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr, ret_ty_is_never: bool) {
102
105
103
106
if check_all_arms {
104
107
for arm in arms {
105
- expr_match ( cx, & arm. body , ret_ty_is_never ) ;
108
+ expr_match ( cx, & arm. body ) ;
106
109
}
107
110
} else {
108
- expr_match (
109
- cx,
110
- & arms. first ( ) . expect ( "if let doesn't have a single arm" ) . body ,
111
- ret_ty_is_never,
112
- ) ;
111
+ expr_match ( cx, & arms. first ( ) . expect ( "if let doesn't have a single arm" ) . body ) ;
113
112
}
114
113
} ,
115
114
// skip if it already has a return statement
116
115
ExprKind :: Ret ( ..) => ( ) ,
117
- // make sure it's not a call that panics unless we intend to return a panic
116
+ // make sure it's not a call that panics
118
117
ExprKind :: Call ( expr, ..) => {
119
118
if_chain ! {
120
119
if let ExprKind :: Path ( qpath) = & expr. node;
121
120
if let Some ( path_def_id) = resolve_node( cx, qpath, expr. hir_id) . opt_def_id( ) ;
122
121
if match_def_path( cx, path_def_id, & BEGIN_PANIC ) ||
123
122
match_def_path( cx, path_def_id, & BEGIN_PANIC_FMT ) ;
124
- then {
125
- // only put `return` on panics if the return type of the function/closure is a panic
126
- if ret_ty_is_never {
127
- lint( cx, expr. span, expr. span, "add `return` as shown" )
128
- }
129
- }
123
+ then { }
130
124
else {
131
- lint( cx, expr. span, expr. span, "add `return` as shown" )
125
+ lint( cx, expr. span, expr. span, LINT_RETURN )
132
126
}
133
127
}
134
128
} ,
135
129
// everything else is missing `return`
136
- _ => lint ( cx, expr. span , expr. span , "add `return` as shown" ) ,
130
+ _ => lint ( cx, expr. span , expr. span , LINT_RETURN ) ,
137
131
}
138
132
}
139
133
@@ -149,12 +143,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn {
149
143
) {
150
144
let def_id = cx. tcx . hir ( ) . body_owner_def_id ( body. id ( ) ) ;
151
145
let mir = cx. tcx . optimized_mir ( def_id) ;
152
- let ret_ty = mir. return_ty ( ) ;
153
146
154
147
// checking return type through MIR, HIR is not able to determine inferred closure return types
155
148
// make sure it's not a macro
156
- if !ret_ty . is_unit ( ) && !in_macro_or_desugar ( span) {
157
- expr_match ( cx, & body. value , ret_ty . is_never ( ) ) ;
149
+ if !mir . return_ty ( ) . is_unit ( ) && !in_macro_or_desugar ( span) {
150
+ expr_match ( cx, & body. value ) ;
158
151
}
159
152
}
160
153
}
0 commit comments