1
1
use clippy_utils:: diagnostics:: { span_lint_and_note, span_lint_and_then} ;
2
2
use clippy_utils:: source:: { first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt} ;
3
3
use clippy_utils:: {
4
- both, count_eq, eq_expr_value, get_enclosing_block, get_parent_expr, if_sequence, in_macro, parent_node_is_if_expr ,
4
+ both, count_eq, eq_expr_value, get_enclosing_block, get_parent_expr, if_sequence, in_macro, is_else_clause ,
5
5
run_lints, search_same, ContainsName , SpanlessEq , SpanlessHash ,
6
6
} ;
7
7
use if_chain:: if_chain;
@@ -188,13 +188,18 @@ fn lint_same_then_else<'tcx>(
188
188
expr : & ' tcx Expr < ' _ > ,
189
189
) {
190
190
// We only lint ifs with multiple blocks
191
- if blocks. len ( ) < 2 || parent_node_is_if_expr ( expr , cx ) {
191
+ if blocks. len ( ) < 2 || is_else_clause ( cx . tcx , expr ) {
192
192
return ;
193
193
}
194
194
195
195
// Check if each block has shared code
196
196
let has_expr = blocks[ 0 ] . expr . is_some ( ) ;
197
- let ( start_eq, mut end_eq, expr_eq) = scan_block_for_eq ( cx, blocks) ;
197
+
198
+ let ( start_eq, mut end_eq, expr_eq) = if let Some ( block_eq) = scan_block_for_eq ( cx, blocks) {
199
+ ( block_eq. start_eq , block_eq. end_eq , block_eq. expr_eq )
200
+ } else {
201
+ return ;
202
+ } ;
198
203
199
204
// BRANCHES_SHARING_CODE prerequisites
200
205
if has_conditional_else || ( start_eq == 0 && end_eq == 0 && ( has_expr && !expr_eq) ) {
@@ -290,15 +295,19 @@ fn lint_same_then_else<'tcx>(
290
295
}
291
296
}
292
297
293
- /// The return tuple is structured as follows:
294
- /// 1. The amount of equal statements from the start
295
- /// 2. The amount of equal statements from the end
296
- /// 3. An indication if the block expressions are the same. This will also be true if both are
297
- /// `None`
298
- ///
299
- /// This function can also trigger the `IF_SAME_THEN_ELSE` in which case it'll return `(0, 0,
300
- /// false)` to aboard any further processing and avoid duplicate lint triggers.
301
- fn scan_block_for_eq ( cx : & LateContext < ' tcx > , blocks : & [ & Block < ' tcx > ] ) -> ( usize , usize , bool ) {
298
+ struct BlockEqual {
299
+ /// The amount statements that are equal from the start
300
+ start_eq : usize ,
301
+ /// The amount statements that are equal from the end
302
+ end_eq : usize ,
303
+ /// An indication if the block expressions are the same. This will also be true if both are
304
+ /// `None`
305
+ expr_eq : bool ,
306
+ }
307
+
308
+ /// This function can also trigger the `IF_SAME_THEN_ELSE` in which case it'll return `None` to
309
+ /// abort any further processing and avoid duplicate lint triggers.
310
+ fn scan_block_for_eq ( cx : & LateContext < ' tcx > , blocks : & [ & Block < ' tcx > ] ) -> Option < BlockEqual > {
302
311
let mut start_eq = usize:: MAX ;
303
312
let mut end_eq = usize:: MAX ;
304
313
let mut expr_eq = true ;
@@ -308,7 +317,7 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize,
308
317
309
318
// `SpanlessEq` now keeps track of the locals and is therefore context sensitive clippy#6752.
310
319
// The comparison therefore needs to be done in a way that builds the correct context.
311
- let mut evaluator = SpanlessEq :: new ( cx) . enable_check_inferred_local_types ( ) ;
320
+ let mut evaluator = SpanlessEq :: new ( cx) ;
312
321
let mut evaluator = evaluator. inter_expr ( ) ;
313
322
314
323
let current_start_eq = count_eq ( & mut l_stmts. iter ( ) , & mut r_stmts. iter ( ) , |l, r| evaluator. eq_stmt ( l, r) ) ;
@@ -340,7 +349,7 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize,
340
349
"same as this" ,
341
350
) ;
342
351
343
- return ( 0 , 0 , false ) ;
352
+ return None ;
344
353
}
345
354
}
346
355
@@ -360,7 +369,11 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize,
360
369
end_eq = min_block_size - start_eq;
361
370
}
362
371
363
- ( start_eq, end_eq, expr_eq)
372
+ Some ( BlockEqual {
373
+ start_eq,
374
+ end_eq,
375
+ expr_eq,
376
+ } )
364
377
}
365
378
366
379
fn check_for_warn_of_moved_symbol (
0 commit comments