Skip to content

Commit 537a7f3

Browse files
committed
Auto merge of #8297 - Jarcho:if_same_then_else_7579, r=Manishearth
Don't lint `if_same_then_else` with `if let` conditions fixes #7579 changelog: Don't lint `if_same_then_else` with `if let` conditions
2 parents 93cad4a + 5461ed6 commit 537a7f3

File tree

2 files changed

+34
-12
lines changed

2 files changed

+34
-12
lines changed

Diff for: clippy_lints/src/copies.rs

+17-12
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for CopyAndPaste {
183183
lint_same_cond(cx, &conds);
184184
lint_same_fns_in_if_cond(cx, &conds);
185185
// Block duplication
186-
lint_same_then_else(cx, &blocks, conds.len() == blocks.len(), expr);
186+
lint_same_then_else(cx, &conds, &blocks, conds.len() == blocks.len(), expr);
187187
}
188188
}
189189
}
@@ -192,6 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for CopyAndPaste {
192192
/// Implementation of `BRANCHES_SHARING_CODE` and `IF_SAME_THEN_ELSE` if the blocks are equal.
193193
fn lint_same_then_else<'tcx>(
194194
cx: &LateContext<'tcx>,
195+
conds: &[&'tcx Expr<'_>],
195196
blocks: &[&Block<'tcx>],
196197
has_conditional_else: bool,
197198
expr: &'tcx Expr<'_>,
@@ -204,7 +205,7 @@ fn lint_same_then_else<'tcx>(
204205
// Check if each block has shared code
205206
let has_expr = blocks[0].expr.is_some();
206207

207-
let (start_eq, mut end_eq, expr_eq) = if let Some(block_eq) = scan_block_for_eq(cx, blocks) {
208+
let (start_eq, mut end_eq, expr_eq) = if let Some(block_eq) = scan_block_for_eq(cx, conds, blocks) {
208209
(block_eq.start_eq, block_eq.end_eq, block_eq.expr_eq)
209210
} else {
210211
return;
@@ -316,14 +317,14 @@ struct BlockEqual {
316317

317318
/// This function can also trigger the `IF_SAME_THEN_ELSE` in which case it'll return `None` to
318319
/// abort any further processing and avoid duplicate lint triggers.
319-
fn scan_block_for_eq(cx: &LateContext<'_>, blocks: &[&Block<'_>]) -> Option<BlockEqual> {
320+
fn scan_block_for_eq(cx: &LateContext<'_>, conds: &[&Expr<'_>], blocks: &[&Block<'_>]) -> Option<BlockEqual> {
320321
let mut start_eq = usize::MAX;
321322
let mut end_eq = usize::MAX;
322323
let mut expr_eq = true;
323-
let mut iter = blocks.windows(2);
324-
while let Some(&[win0, win1]) = iter.next() {
325-
let l_stmts = win0.stmts;
326-
let r_stmts = win1.stmts;
324+
let mut iter = blocks.windows(2).enumerate();
325+
while let Some((i, &[block0, block1])) = iter.next() {
326+
let l_stmts = block0.stmts;
327+
let r_stmts = block1.stmts;
327328

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

345346
// IF_SAME_THEN_ELSE
346347
if_chain! {
347348
if block_expr_eq;
348349
if l_stmts.len() == r_stmts.len();
349350
if l_stmts.len() == current_start_eq;
350-
if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, win0.hir_id);
351-
if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, win1.hir_id);
351+
// `conds` may have one last item than `blocks`.
352+
// Any `i` from `blocks.windows(2)` will exist in `conds`, but `i+1` may not exist on the last iteration.
353+
if !matches!(conds[i].kind, ExprKind::Let(..));
354+
if !matches!(conds.get(i + 1).map(|e| &e.kind), Some(ExprKind::Let(..)));
355+
if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, block0.hir_id);
356+
if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, block1.hir_id);
352357
then {
353358
span_lint_and_note(
354359
cx,
355360
IF_SAME_THEN_ELSE,
356-
win0.span,
361+
block0.span,
357362
"this `if` has identical blocks",
358-
Some(win1.span),
363+
Some(block1.span),
359364
"same as this",
360365
);
361366

Diff for: tests/ui/if_same_then_else2.rs

+17
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,23 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
138138
let (y, x) = (1, 2);
139139
return Ok(&foo[x..y]);
140140
}
141+
142+
// Issue #7579
143+
let _ = if let Some(0) = None { 0 } else { 0 };
144+
145+
if true {
146+
return Err(());
147+
} else if let Some(0) = None {
148+
return Err(());
149+
}
150+
151+
let _ = if let Some(0) = None {
152+
0
153+
} else if let Some(1) = None {
154+
0
155+
} else {
156+
0
157+
};
141158
}
142159

143160
fn main() {}

0 commit comments

Comments
 (0)