Adapted the lint to use the new SpanlessEq

This commit is contained in:
xFrednet 2021-02-23 21:16:19 +01:00
parent 65ed5a632f
commit c74e49eab9
10 changed files with 111 additions and 196 deletions

View file

@ -295,11 +295,21 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize,
let l_stmts = win[0].stmts;
let r_stmts = win[1].stmts;
// `SpanlessEq` now keeps track of the locals and is therefore context sensitive clippy#6752.
// The comparison therefor needs to be done in a way that builds the correct context.
let mut evaluator = SpanlessEq::new(cx);
let mut evaluator = evaluator.inter_expr();
let current_start_eq = count_eq(&mut l_stmts.iter(), &mut r_stmts.iter(), |l, r| evaluator.eq_stmt(l, r));
let current_end_eq = count_eq(&mut l_stmts.iter().rev(), &mut r_stmts.iter().rev(), |l, r| {
evaluator.eq_stmt(l, r)
});
let current_end_eq = {
// We skip the middle statements which can't be equal
let end_comparison_count = l_stmts.len().min(r_stmts.len()) - current_start_eq;
let it1 = l_stmts.iter().skip(l_stmts.len() - end_comparison_count);
let it2 = r_stmts.iter().skip(r_stmts.len() - end_comparison_count);
it1.zip(it2)
.fold(0, |acc, (l, r)| if evaluator.eq_stmt(l, r) { acc + 1 } else { 0 })
};
let block_expr_eq = both(&win[0].expr, &win[1].expr, |l, r| evaluator.eq_expr(l, r));
// IF_SAME_THEN_ELSE
@ -458,8 +468,8 @@ fn emit_shared_code_in_if_blocks_lint(
// Emit lint
if suggestions.len() == 1 {
let (place_str, span, sugg) = suggestions.pop().unwrap();
let msg = format!("All if blocks contain the same code at the {}", place_str);
let help = format!("Consider moving the {} statements out like this", place_str);
let msg = format!("all if blocks contain the same code at the {}", place_str);
let help = format!("consider moving the {} statements out like this", place_str);
span_lint_and_then(cx, SHARED_CODE_IN_IF_BLOCKS, span, msg.as_str(), |diag| {
diag.span_suggestion(span, help.as_str(), sugg, Applicability::Unspecified);
@ -472,20 +482,20 @@ fn emit_shared_code_in_if_blocks_lint(
cx,
SHARED_CODE_IN_IF_BLOCKS,
start_span,
"All if blocks contain the same code at the start and the end. Here at the start:",
"all if blocks contain the same code at the start and the end. Here at the start",
move |diag| {
diag.span_note(end_span, "And here at the end:");
diag.span_note(end_span, "and here at the end");
diag.span_suggestion(
start_span,
"Consider moving the start statements out like this:",
"consider moving the start statements out like this",
start_sugg,
Applicability::Unspecified,
);
diag.span_suggestion(
end_span,
"And consider moving the end statements out like this:",
"and consider moving the end statements out like this",
end_sugg,
Applicability::Unspecified,
);

View file

@ -58,13 +58,14 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
/// Use this method to wrap comparisons that may involve inter-expression context.
/// See `self.locals`.
fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> {
pub fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> {
HirEqInterExpr {
inner: self,
locals: HirIdMap::default(),
}
}
#[allow(dead_code)]
pub fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool {
self.inter_expr().eq_block(left, right)
}
@ -82,7 +83,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
}
}
struct HirEqInterExpr<'a, 'b, 'tcx> {
pub struct HirEqInterExpr<'a, 'b, 'tcx> {
inner: &'a mut SpanlessEq<'b, 'tcx>,
// When binding are declared, the binding ID in the left expression is mapped to the one on the
@ -92,7 +93,7 @@ struct HirEqInterExpr<'a, 'b, 'tcx> {
}
impl HirEqInterExpr<'_, '_, '_> {
fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
match (&left.kind, &right.kind) {
(&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => {
self.eq_pat(&l.pat, &r.pat)
@ -159,7 +160,7 @@ impl HirEqInterExpr<'_, '_, '_> {
}
#[allow(clippy::similar_names)]
fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
if !self.inner.allow_side_effects && differing_macro_contexts(left.span, right.span) {
return false;
}

View file

@ -82,31 +82,5 @@ LL | | 42
LL | | };
| |_____^
error: this `if` has identical blocks
--> $DIR/if_same_then_else.rs:95:13
|
LL | if true {
| _____________^
LL | | let bar = if true { 42 } else { 43 };
LL | |
LL | | while foo() {
... |
LL | | bar + 1;
LL | | } else {
| |_____^
|
note: same as this
--> $DIR/if_same_then_else.rs:102:12
|
LL | } else {
| ____________^
LL | | //~ ERROR same body as `if` block
LL | | let bar = if true { 42 } else { 43 };
LL | |
... |
LL | | bar + 1;
LL | | }
| |_____^
error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

View file

@ -1,19 +1,5 @@
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:21:12
|
LL | } else {
| ____________^
LL | | //~ ERROR same body as `if` block
LL | | for _ in &[42] {
LL | | let bar: &Option<_> = &Some::<u8>(42);
... |
LL | | }
LL | | }
| |_____^
|
= note: `-D clippy::if-same-then-else` implied by `-D warnings`
note: same as this
--> $DIR/if_same_then_else2.rs:12:13
--> $DIR/if_same_then_else2.rs:13:13
|
LL | if true {
| _____________^
@ -33,7 +19,7 @@ LL | } else {
| ____________^
LL | | //~ ERROR same body as `if` block
LL | | for _ in &[42] {
LL | | let foo: &Option<_> = &Some::<u8>(42);
LL | | let bar: &Option<_> = &Some::<u8>(42);
... |
LL | | }
LL | | }
@ -115,25 +101,5 @@ LL | | Ok("foo")?;
LL | | }
| |_____^
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:122:20
|
LL | } else if true {
| ____________________^
LL | | let foo = "";
LL | | return Ok(&foo[0..]);
LL | | } else {
| |_____^
|
note: same as this
--> $DIR/if_same_then_else2.rs:125:12
|
LL | } else {
| ____________^
LL | | let foo = "";
LL | | return Ok(&foo[0..]);
LL | | }
| |_____^
error: aborting due to 6 previous errors
error: aborting due to 5 previous errors

View file

@ -4,7 +4,6 @@
// This tests the shared_code_in_if_blocks lint at the end of blocks
fn simple_examples() {
// TODO xFrednet 2021-01-06: Test with const literals at the end
let x = 1;
let _ = if x == 7 {
@ -45,8 +44,8 @@ fn simple_examples() {
println!("This is also eq with the else block");
println!("Same end of block");
} else {
println!("Same end of block");
println!("This is also eq with the else block");
println!("Same end of block");
}
// Use of outer scope value
@ -69,21 +68,11 @@ fn simple_examples() {
);
}
// TODO xFrednet 2021-01.13: Fix lint for `if let`
let index = Some(8);
if let Some(index) = index {
println!("The index is: {}", index);
println!("Same end of block");
} else {
println!("Same end of block");
}
if x == 9 {
if x == 8 {
// No parent!!
println!("Hello World");
println!("---");
println!("Hello World");
} else {
println!("Hello World");
}

View file

@ -1,5 +1,5 @@
error: All if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:31:5
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:30:5
|
LL | / let result = false;
LL | | println!("Block end!");
@ -13,7 +13,7 @@ note: the lint level is defined here
LL | #![deny(clippy::if_same_then_else, clippy::shared_code_in_if_blocks)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: The end suggestion probably needs some adjustments to use the expression result correctly.
help: Consider moving the end statements out like this
help: consider moving the end statements out like this
|
LL | }
LL | let result = false;
@ -21,8 +21,21 @@ LL | println!("Block end!");
LL | result;
|
error: All if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:66:5
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:48:5
|
LL | / println!("Same end of block");
LL | | }
| |_____^
|
help: consider moving the end statements out like this
|
LL | }
LL | println!("Same end of block");
|
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:65:5
|
LL | / println!(
LL | | "I'm moveable because I know: `outer_scope_value`: '{}'",
@ -31,7 +44,7 @@ LL | | );
LL | | }
| |_____^
|
help: Consider moving the end statements out like this
help: consider moving the end statements out like this
|
LL | }
LL | println!(
@ -40,22 +53,21 @@ LL | outer_scope_value
LL | );
|
error: All if blocks contain the same code at the start
--> $DIR/shared_at_bot.rs:83:9
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:77:9
|
LL | / if x == 8 {
LL | | // No parent!!
LL | | println!("Hello World");
| |____________________________________^
LL | / println!("Hello World");
LL | | }
| |_________^
|
help: Consider moving the start statements out like this
help: consider moving the end statements out like this
|
LL | }
LL | println!("Hello World");
LL | if x == 8 {
|
error: All if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:104:5
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:93:5
|
LL | / let later_used_value = "A string value";
LL | | println!("{}", later_used_value);
@ -64,15 +76,15 @@ LL | | }
| |_____^
|
= warning: Some moved values might need to be renamed to avoid wrong references.
help: Consider moving the end statements out like this
help: consider moving the end statements out like this
|
LL | }
LL | let later_used_value = "A string value";
LL | println!("{}", later_used_value);
|
error: All if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:117:5
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:106:5
|
LL | / let simple_examples = "I now identify as a &str :)";
LL | | println!("This is the new simple_example: {}", simple_examples);
@ -80,52 +92,52 @@ LL | | }
| |_____^
|
= warning: Some moved values might need to be renamed to avoid wrong references.
help: Consider moving the end statements out like this
help: consider moving the end statements out like this
|
LL | }
LL | let simple_examples = "I now identify as a &str :)";
LL | println!("This is the new simple_example: {}", simple_examples);
|
error: All if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:182:5
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:171:5
|
LL | / x << 2
LL | | };
| |_____^
|
= note: The end suggestion probably needs some adjustments to use the expression result correctly.
help: Consider moving the end statements out like this
help: consider moving the end statements out like this
|
LL | }
LL | x << 2;
|
error: All if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:189:5
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:178:5
|
LL | / x * 4
LL | | }
| |_____^
|
= note: The end suggestion probably needs some adjustments to use the expression result correctly.
help: Consider moving the end statements out like this
help: consider moving the end statements out like this
|
LL | }
LL | x * 4
|
error: All if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:201:44
error: all if blocks contain the same code at the end
--> $DIR/shared_at_bot.rs:190:44
|
LL | if x == 17 { b = 1; a = 0x99; } else { a = 0x99; }
| ^^^^^^^^^^^
|
help: Consider moving the end statements out like this
help: consider moving the end statements out like this
|
LL | if x == 17 { b = 1; a = 0x99; } else { }
LL | a = 0x99;
|
error: aborting due to 8 previous errors
error: aborting due to 9 previous errors

View file

@ -1,4 +1,4 @@
error: All if blocks contain the same code at the start
error: all if blocks contain the same code at the start
--> $DIR/shared_at_top.rs:10:5
|
LL | / if true {
@ -10,13 +10,13 @@ note: the lint level is defined here
|
LL | #![deny(clippy::if_same_then_else, clippy::shared_code_in_if_blocks)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: Consider moving the start statements out like this
help: consider moving the start statements out like this
|
LL | println!("Hello World!");
LL | if true {
|
error: All if blocks contain the same code at the start
error: all if blocks contain the same code at the start
--> $DIR/shared_at_top.rs:19:5
|
LL | / if x == 0 {
@ -26,7 +26,7 @@ LL | | let _z = y;
| |___________________^
|
= warning: Some moved values might need to be renamed to avoid wrong references.
help: Consider moving the start statements out like this
help: consider moving the start statements out like this
|
LL | let y = 9;
LL | println!("The value y was set to: `{}`", y);
@ -34,20 +34,20 @@ LL | let _z = y;
LL | if x == 0 {
|
error: All if blocks contain the same code at the start
error: all if blocks contain the same code at the start
--> $DIR/shared_at_top.rs:40:5
|
LL | / let _ = if x == 7 {
LL | | let y = 16;
| |___________________^
|
help: Consider moving the start statements out like this
help: consider moving the start statements out like this
|
LL | let y = 16;
LL | let _ = if x == 7 {
|
error: All if blocks contain the same code at the start
error: all if blocks contain the same code at the start
--> $DIR/shared_at_top.rs:58:5
|
LL | / if x == 10 {
@ -56,14 +56,14 @@ LL | | println!("Str: {}", used_value_name);
| |_____________________________________________^
|
= warning: Some moved values might need to be renamed to avoid wrong references.
help: Consider moving the start statements out like this
help: consider moving the start statements out like this
|
LL | let used_value_name = "Different type";
LL | println!("Str: {}", used_value_name);
LL | if x == 10 {
|
error: All if blocks contain the same code at the start
error: all if blocks contain the same code at the start
--> $DIR/shared_at_top.rs:72:5
|
LL | / if x == 11 {
@ -72,14 +72,14 @@ LL | | println!("I'm also moveable");
| |______________________________________^
|
= warning: Some moved values might need to be renamed to avoid wrong references.
help: Consider moving the start statements out like this
help: consider moving the start statements out like this
|
LL | let can_be_overridden = "Move me";
LL | println!("I'm also moveable");
LL | if x == 11 {
|
error: All if blocks contain the same code at the start
error: all if blocks contain the same code at the start
--> $DIR/shared_at_top.rs:88:5
|
LL | / if x == 2020 {
@ -87,7 +87,7 @@ LL | | println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint
LL | | println!("Because `IF_SAME_THEN_ELSE` is allowed here");
| |________________________________________________________________^
|
help: Consider moving the start statements out like this
help: consider moving the start statements out like this
|
LL | println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint.");
LL | println!("Because `IF_SAME_THEN_ELSE` is allowed here");

View file

@ -1,4 +1,4 @@
error: All if blocks contain the same code at the start and the end. Here at the start:
error: all if blocks contain the same code at the start and the end. Here at the start
--> $DIR/shared_at_top_and_bot.rs:16:5
|
LL | / if x == 7 {
@ -12,26 +12,26 @@ note: the lint level is defined here
|
LL | #![deny(clippy::if_same_then_else, clippy::shared_code_in_if_blocks)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: And here at the end:
note: and here at the end
--> $DIR/shared_at_top_and_bot.rs:28:5
|
LL | / let _u = 9;
LL | | }
| |_____^
help: Consider moving the start statements out like this:
help: consider moving the start statements out like this
|
LL | let t = 7;
LL | let _overlap_start = t * 2;
LL | let _overlap_end = 2 * t;
LL | if x == 7 {
|
help: And consider moving the end statements out like this:
help: and consider moving the end statements out like this
|
LL | }
LL | let _u = 9;
|
error: All if blocks contain the same code at the start and the end. Here at the start:
error: all if blocks contain the same code at the start and the end. Here at the start
--> $DIR/shared_at_top_and_bot.rs:32:5
|
LL | / if x == 99 {
@ -40,7 +40,7 @@ LL | | let _overlap_start = r;
LL | | let _overlap_middle = r * r;
| |____________________________________^
|
note: And here at the end:
note: and here at the end
--> $DIR/shared_at_top_and_bot.rs:43:5
|
LL | / let _overlap_end = r * r * r;
@ -48,21 +48,21 @@ LL | | let z = "end";
LL | | }
| |_____^
= warning: Some moved values might need to be renamed to avoid wrong references.
help: Consider moving the start statements out like this:
help: consider moving the start statements out like this
|
LL | let r = 7;
LL | let _overlap_start = r;
LL | let _overlap_middle = r * r;
LL | if x == 99 {
|
help: And consider moving the end statements out like this:
help: and consider moving the end statements out like this
|
LL | }
LL | let _overlap_end = r * r * r;
LL | let z = "end";
|
error: All if blocks contain the same code at the start and the end. Here at the start:
error: all if blocks contain the same code at the start and the end. Here at the start
--> $DIR/shared_at_top_and_bot.rs:61:5
|
LL | / if (x > 7 && y < 13) || (x + y) % 2 == 1 {
@ -71,7 +71,7 @@ LL | | let b = 0xffff00ff;
LL | | let e_id = gen_id(a, b);
| |________________________________^
|
note: And here at the end:
note: and here at the end
--> $DIR/shared_at_top_and_bot.rs:81:5
|
LL | / let pack = DataPack {
@ -83,14 +83,14 @@ LL | | process_data(pack);
LL | | }
| |_____^
= warning: Some moved values might need to be renamed to avoid wrong references.
help: Consider moving the start statements out like this:
help: consider moving the start statements out like this
|
LL | let a = 0xcafe;
LL | let b = 0xffff00ff;
LL | let e_id = gen_id(a, b);
LL | if (x > 7 && y < 13) || (x + y) % 2 == 1 {
|
help: And consider moving the end statements out like this:
help: and consider moving the end statements out like this
|
LL | }
LL | let pack = DataPack {
@ -100,51 +100,51 @@ LL | some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90],
LL | };
...
error: All if blocks contain the same code at the start and the end. Here at the start:
error: all if blocks contain the same code at the start and the end. Here at the start
--> $DIR/shared_at_top_and_bot.rs:94:5
|
LL | / let _ = if x == 7 {
LL | | let _ = 19;
| |___________________^
|
note: And here at the end:
note: and here at the end
--> $DIR/shared_at_top_and_bot.rs:103:5
|
LL | / x << 2
LL | | };
| |_____^
= note: The end suggestion probably needs some adjustments to use the expression result correctly.
help: Consider moving the start statements out like this:
help: consider moving the start statements out like this
|
LL | let _ = 19;
LL | let _ = if x == 7 {
|
help: And consider moving the end statements out like this:
help: and consider moving the end statements out like this
|
LL | }
LL | x << 2;
|
error: All if blocks contain the same code at the start and the end. Here at the start:
error: all if blocks contain the same code at the start and the end. Here at the start
--> $DIR/shared_at_top_and_bot.rs:106:5
|
LL | / if x == 9 {
LL | | let _ = 17;
| |___________________^
|
note: And here at the end:
note: and here at the end
--> $DIR/shared_at_top_and_bot.rs:115:5
|
LL | / x * 4
LL | | }
| |_____^
= note: The end suggestion probably needs some adjustments to use the expression result correctly.
help: Consider moving the start statements out like this:
help: consider moving the start statements out like this
|
LL | let _ = 17;
LL | if x == 9 {
|
help: And consider moving the end statements out like this:
help: and consider moving the end statements out like this
|
LL | }
LL | x * 4

View file

@ -109,23 +109,6 @@ fn trigger_other_lint() {
let _ = "This is a string";
}
// More complex same blocks
if x == 17 {
#[derive(Debug)]
struct Duck {
num: u64,
};
let pet = Duck { num: 18 };
println!("{:?}", pet);
} else {
#[derive(Debug)]
struct Duck {
num: u64,
};
let pet = Duck { num: 18 };
println!("{:?}", pet);
}
// Only same expression
let _ = if x == 6 { 7 } else { 7 };

View file

@ -25,40 +25,20 @@ LL | | let _ = "This is a string";
LL | | }
| |_____^
error: All if blocks contain the same code at the end
--> $DIR/valid_if_blocks.rs:125:5
|
LL | / let pet = Duck { num: 18 };
LL | | println!("{:?}", pet);
LL | | }
| |_____^
|
note: the lint level is defined here
--> $DIR/valid_if_blocks.rs:2:36
|
LL | #![deny(clippy::if_same_then_else, clippy::shared_code_in_if_blocks)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: Consider moving the end statements out like this
|
LL | }
LL | let pet = Duck { num: 18 };
LL | println!("{:?}", pet);
|
error: this `if` has identical blocks
--> $DIR/valid_if_blocks.rs:130:23
--> $DIR/valid_if_blocks.rs:113:23
|
LL | let _ = if x == 6 { 7 } else { 7 };
| ^^^^^
|
note: same as this
--> $DIR/valid_if_blocks.rs:130:34
--> $DIR/valid_if_blocks.rs:113:34
|
LL | let _ = if x == 6 { 7 } else { 7 };
| ^^^^^
error: this `if` has identical blocks
--> $DIR/valid_if_blocks.rs:136:23
--> $DIR/valid_if_blocks.rs:119:23
|
LL | } else if x == 68 {
| _______________________^
@ -71,7 +51,7 @@ LL | | } else {
| |_____^
|
note: same as this
--> $DIR/valid_if_blocks.rs:145:12
--> $DIR/valid_if_blocks.rs:128:12
|
LL | } else {
| ____________^
@ -84,7 +64,7 @@ LL | | };
| |_____^
error: this `if` has identical blocks
--> $DIR/valid_if_blocks.rs:158:23
--> $DIR/valid_if_blocks.rs:141:23
|
LL | } else if x == 68 {
| _______________________^
@ -94,7 +74,7 @@ LL | | } else {
| |_____^
|
note: same as this
--> $DIR/valid_if_blocks.rs:161:12
--> $DIR/valid_if_blocks.rs:144:12
|
LL | } else {
| ____________^
@ -103,5 +83,5 @@ LL | | println!("I'm a doppelgänger");
LL | | }
| |_____^
error: aborting due to 5 previous errors
error: aborting due to 4 previous errors