Skip to content

Commit

Permalink
Don't lint if_same_then_else with if let conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarcho committed Jan 16, 2022
1 parent 0d27bd8 commit e2f0a32
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 12 deletions.
27 changes: 15 additions & 12 deletions clippy_lints/src/copies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for CopyAndPaste {
lint_same_cond(cx, &conds);
lint_same_fns_in_if_cond(cx, &conds);
// Block duplication
lint_same_then_else(cx, &blocks, conds.len() == blocks.len(), expr);
lint_same_then_else(cx, &conds, &blocks, conds.len() == blocks.len(), expr);
}
}
}
Expand All @@ -192,6 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for CopyAndPaste {
/// Implementation of `BRANCHES_SHARING_CODE` and `IF_SAME_THEN_ELSE` if the blocks are equal.
fn lint_same_then_else<'tcx>(
cx: &LateContext<'tcx>,
conds: &[&'tcx Expr<'_>],
blocks: &[&Block<'tcx>],
has_conditional_else: bool,
expr: &'tcx Expr<'_>,
Expand All @@ -204,7 +205,7 @@ fn lint_same_then_else<'tcx>(
// Check if each block has shared code
let has_expr = blocks[0].expr.is_some();

let (start_eq, mut end_eq, expr_eq) = if let Some(block_eq) = scan_block_for_eq(cx, blocks) {
let (start_eq, mut end_eq, expr_eq) = if let Some(block_eq) = scan_block_for_eq(cx, conds, blocks) {
(block_eq.start_eq, block_eq.end_eq, block_eq.expr_eq)
} else {
return;
Expand Down Expand Up @@ -316,14 +317,14 @@ struct BlockEqual {

/// This function can also trigger the `IF_SAME_THEN_ELSE` in which case it'll return `None` to
/// abort any further processing and avoid duplicate lint triggers.
fn scan_block_for_eq(cx: &LateContext<'_>, blocks: &[&Block<'_>]) -> Option<BlockEqual> {
fn scan_block_for_eq(cx: &LateContext<'_>, conds: &[&Expr<'_>], blocks: &[&Block<'_>]) -> Option<BlockEqual> {
let mut start_eq = usize::MAX;
let mut end_eq = usize::MAX;
let mut expr_eq = true;
let mut iter = blocks.windows(2);
while let Some(&[win0, win1]) = iter.next() {
let l_stmts = win0.stmts;
let r_stmts = win1.stmts;
let mut iter = conds.windows(2).zip(blocks.windows(2));
while let Some((&[cond0, cond1], &[block0, block1])) = iter.next() {
let l_stmts = block0.stmts;
let r_stmts = block1.stmts;

// `SpanlessEq` now keeps track of the locals and is therefore context sensitive clippy#6752.
// The comparison therefore needs to be done in a way that builds the correct context.
Expand All @@ -340,22 +341,24 @@ fn scan_block_for_eq(cx: &LateContext<'_>, blocks: &[&Block<'_>]) -> Option<Bloc
it1.zip(it2)
.fold(0, |acc, (l, r)| if evaluator.eq_stmt(l, r) { acc + 1 } else { 0 })
};
let block_expr_eq = both(&win0.expr, &win1.expr, |l, r| evaluator.eq_expr(l, r));
let block_expr_eq = both(&block0.expr, &block1.expr, |l, r| evaluator.eq_expr(l, r));

// IF_SAME_THEN_ELSE
if_chain! {
if block_expr_eq;
if !matches!(cond0.kind, ExprKind::Let(..));
if !matches!(cond1.kind, ExprKind::Let(..));
if l_stmts.len() == r_stmts.len();
if l_stmts.len() == current_start_eq;
if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, win0.hir_id);
if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, win1.hir_id);
if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, block0.hir_id);
if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, block1.hir_id);
then {
span_lint_and_note(
cx,
IF_SAME_THEN_ELSE,
win0.span,
block0.span,
"this `if` has identical blocks",
Some(win1.span),
Some(block1.span),
"same as this",
);

Expand Down
17 changes: 17 additions & 0 deletions tests/ui/if_then_some_else_none.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ fn main() {

// Should not issue an error since the `then` block doesn't use `Some` directly.
let _ = if foo() { into_some("foo") } else { None };

// Issue #7579
let _ = if let Some(0) = None { 0 } else { 0 };

let _ = if true {
0
} else if let Some(0) = None {
0
};

let _ = if let Some(0) = None {
0
} else if let None = None {
0
} else {
0
};
}

fn _msrv_1_49() {
Expand Down

0 comments on commit e2f0a32

Please sign in to comment.