@@ -180,11 +180,11 @@ fn lint_same_then_else(cx: &LateContext<'_>, blocks: &[&Block<'_>], has_uncondit
180
180
}
181
181
}
182
182
183
- fn lint_duplicate_code ( cx : & LateContext < ' _ > , position : & str , lint_span : Span ) {
183
+ fn lint_duplicate_code ( cx : & LateContext < ' _ > , position : & str , lint_start : Span , lint_end : Span ) {
184
184
span_lint_and_help (
185
185
cx,
186
186
SHARED_CODE_IN_IF_BLOCKS ,
187
- lint_span ,
187
+ lint_start . to ( lint_end ) ,
188
188
format ! ( "All if blocks contain the same code at the {}" , position) . as_str ( ) ,
189
189
None ,
190
190
"Consider moving the code out of the if statement to prevent code duplication" ,
@@ -196,9 +196,16 @@ fn lint_same_then_else(cx: &LateContext<'_>, blocks: &[&Block<'_>], has_uncondit
196
196
return ;
197
197
}
198
198
199
+ let eval_expr = if let Some ( expr) = blocks[ 0 ] . expr {
200
+ cx. typeck_results ( ) . expr_ty ( expr) . is_unit ( )
201
+ } else {
202
+ false
203
+ } ;
204
+
199
205
// Check if each block has shared code
200
206
let mut start_eq = usize:: MAX ;
201
207
let mut end_eq = usize:: MAX ;
208
+ let mut expr_eq = true ;
202
209
for ( index, win) in blocks. windows ( 2 ) . enumerate ( ) {
203
210
let l_stmts = win[ 0 ] . stmts ;
204
211
let r_stmts = win[ 1 ] . stmts ;
@@ -208,12 +215,13 @@ fn lint_same_then_else(cx: &LateContext<'_>, blocks: &[&Block<'_>], has_uncondit
208
215
let current_end_eq = count_eq ( & mut l_stmts. iter ( ) . rev ( ) , & mut r_stmts. iter ( ) . rev ( ) , |l, r| {
209
216
evaluator. eq_stmt ( l, r)
210
217
} ) ;
211
- let current_block_expr_eq = both ( & win[ 0 ] . expr , & win[ 1 ] . expr , |l, r| evaluator. eq_expr ( l, r) ) ;
218
+
219
+ let block_expr_eq = both ( & win[ 0 ] . expr , & win[ 1 ] . expr , |l, r| evaluator. eq_expr ( l, r) ) ;
212
220
213
221
// IF_SAME_THEN_ELSE
214
222
// We only lint the first two blocks (index == 0). Further blocks will be linted when that if
215
223
// statement is checked
216
- if index == 0 && current_block_expr_eq && l_stmts. len ( ) == r_stmts. len ( ) && l_stmts. len ( ) == current_start_eq {
224
+ if index == 0 && block_expr_eq && l_stmts. len ( ) == r_stmts. len ( ) && l_stmts. len ( ) == current_start_eq {
217
225
span_lint_and_note (
218
226
cx,
219
227
IF_SAME_THEN_ELSE ,
@@ -228,9 +236,10 @@ fn lint_same_then_else(cx: &LateContext<'_>, blocks: &[&Block<'_>], has_uncondit
228
236
229
237
start_eq = min ( start_eq, current_start_eq) ;
230
238
end_eq = min ( end_eq, current_end_eq) ;
239
+ expr_eq = expr_eq && block_expr_eq;
231
240
232
241
// We can return if the eq count is 0 from both sides or if it has no unconditional else case
233
- if !has_unconditional_else || start_eq == 0 && end_eq == 0 {
242
+ if !has_unconditional_else || ( start_eq == 0 && end_eq == 0 && ! ( eval_expr && expr_eq ) ) {
234
243
return ;
235
244
} ;
236
245
}
@@ -245,18 +254,22 @@ fn lint_same_then_else(cx: &LateContext<'_>, blocks: &[&Block<'_>], has_uncondit
245
254
if start_eq != 0 {
246
255
let start = first_block. span . shrink_to_lo ( ) ;
247
256
let end = get_source_span ( first_block. stmts [ start_eq - 1 ] . span ) ;
248
- let lint_span = start. to ( end) ;
249
257
250
- lint_duplicate_code ( cx, "start" , lint_span ) ;
258
+ lint_duplicate_code ( cx, "start" , start , end ) ;
251
259
}
252
260
253
- if end_eq != 0 {
261
+ let lint_end = first_block. span . shrink_to_hi ( ) ;
262
+ if end_eq != 0 && ( !eval_expr || expr_eq) {
254
263
let index = first_block. stmts . len ( ) - end_eq;
255
264
let start = get_source_span ( first_block. stmts [ index] . span ) ;
256
- let end = first_block. span . shrink_to_hi ( ) ;
257
- let lint_span = start. to ( end) ;
265
+
266
+ lint_duplicate_code ( cx, "end" , start, lint_end) ;
267
+ } else if eval_expr && expr_eq {
268
+ if let Some ( expr) = first_block. expr {
269
+ let start = get_source_span ( expr. span ) ;
258
270
259
- lint_duplicate_code ( cx, "end" , lint_span) ;
271
+ lint_duplicate_code ( cx, "end" , start, lint_end) ;
272
+ } ;
260
273
}
261
274
}
262
275
0 commit comments