Skip to content

Commit eaf0f3d

Browse files
committed
Auto merge of #7075 - xFrednet:7054-fp-branches-sharing-code, r=camsteffen,flip1995
Fixing FPs for the `branches_sharing_code` lint Fixes #7053 Fixes #7054 And an additional CSS adjustment to support dark mode for every inline code. It currently only works in paragraphs, which was an oversight on my part 😅. [Current Example](https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name) This also includes ~50 lines of doc comments and is therefor not as big as the changes would indicate. 🐧 --- changelog: none All of these bugs were introduced in this dev version and are therefor not worth a change log entry. r? `@phansch` cc: `@camsteffen` since you have a pretty good overview of the `SpanlessEq` implementation 🙃
2 parents 28dbcd8 + 0b4af72 commit eaf0f3d

File tree

9 files changed

+69
-28
lines changed

9 files changed

+69
-28
lines changed

clippy_lints/src/comparison_chain.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_help;
22
use clippy_utils::ty::implements_trait;
3-
use clippy_utils::{get_trait_def_id, if_sequence, parent_node_is_if_expr, paths, SpanlessEq};
3+
use clippy_utils::{get_trait_def_id, if_sequence, is_else_clause, paths, SpanlessEq};
44
use rustc_hir::{BinOpKind, Expr, ExprKind};
55
use rustc_lint::{LateContext, LateLintPass};
66
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain {
6060
}
6161

6262
// We only care about the top-most `if` in the chain
63-
if parent_node_is_if_expr(expr, cx) {
63+
if is_else_clause(cx.tcx, expr) {
6464
return;
6565
}
6666

clippy_lints/src/copies.rs

+27-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
22
use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt};
33
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,
55
run_lints, search_same, ContainsName, SpanlessEq, SpanlessHash,
66
};
77
use if_chain::if_chain;
@@ -188,13 +188,18 @@ fn lint_same_then_else<'tcx>(
188188
expr: &'tcx Expr<'_>,
189189
) {
190190
// 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) {
192192
return;
193193
}
194194

195195
// Check if each block has shared code
196196
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+
};
198203

199204
// BRANCHES_SHARING_CODE prerequisites
200205
if has_conditional_else || (start_eq == 0 && end_eq == 0 && (has_expr && !expr_eq)) {
@@ -290,7 +295,19 @@ fn lint_same_then_else<'tcx>(
290295
}
291296
}
292297

293-
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> {
294311
let mut start_eq = usize::MAX;
295312
let mut end_eq = usize::MAX;
296313
let mut expr_eq = true;
@@ -332,7 +349,7 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize,
332349
"same as this",
333350
);
334351

335-
return (0, 0, false);
352+
return None;
336353
}
337354
}
338355

@@ -352,7 +369,11 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize,
352369
end_eq = min_block_size - start_eq;
353370
}
354371

355-
(start_eq, end_eq, expr_eq)
372+
Some(BlockEqual {
373+
start_eq,
374+
end_eq,
375+
expr_eq,
376+
})
356377
}
357378

358379
fn check_for_warn_of_moved_symbol(

clippy_lints/src/if_then_some_else_none.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_help;
22
use clippy_utils::source::snippet_with_macro_callsite;
3-
use clippy_utils::{is_lang_ctor, meets_msrv, parent_node_is_if_expr};
3+
use clippy_utils::{is_else_clause, is_lang_ctor, meets_msrv};
44
use if_chain::if_chain;
55
use rustc_hir::LangItem::{OptionNone, OptionSome};
66
use rustc_hir::{Expr, ExprKind};
@@ -68,7 +68,7 @@ impl LateLintPass<'_> for IfThenSomeElseNone {
6868
}
6969

7070
// We only care about the top-most `if` in the chain
71-
if parent_node_is_if_expr(expr, cx) {
71+
if is_else_clause(cx.tcx, expr) {
7272
return;
7373
}
7474

clippy_lints/src/needless_bool.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
66
use clippy_utils::source::snippet_with_applicability;
77
use clippy_utils::sugg::Sugg;
8-
use clippy_utils::{is_expn_of, parent_node_is_if_expr};
8+
use clippy_utils::{is_else_clause, is_expn_of};
99
use rustc_ast::ast::LitKind;
1010
use rustc_errors::Applicability;
1111
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
8181
snip = snip.make_return();
8282
}
8383

84-
if parent_node_is_if_expr(e, cx) {
84+
if is_else_clause(cx.tcx, e) {
8585
snip = snip.blockify()
8686
}
8787

clippy_utils/src/hir_utils.rs

+10
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ impl HirEqInterExpr<'_, '_, '_> {
9696
pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
9797
match (&left.kind, &right.kind) {
9898
(&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => {
99+
// This additional check ensures that the type of the locals are equivalent even if the init
100+
// expression or type have some inferred parts.
101+
if let Some(typeck) = self.inner.maybe_typeck_results {
102+
let l_ty = typeck.pat_ty(&l.pat);
103+
let r_ty = typeck.pat_ty(&r.pat);
104+
if !rustc_middle::ty::TyS::same_type(l_ty, r_ty) {
105+
return false;
106+
}
107+
}
108+
99109
// eq_pat adds the HirIds to the locals map. We therefor call it last to make sure that
100110
// these only get added if the init and type is equal.
101111
both(&l.init, &r.init, |l, r| self.eq_expr(l, r))

clippy_utils/src/lib.rs

-15
Original file line numberDiff line numberDiff line change
@@ -1300,21 +1300,6 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
13001300
(conds, blocks)
13011301
}
13021302

1303-
/// This function returns true if the given expression is the `else` or `if else` part of an if
1304-
/// statement
1305-
pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
1306-
let map = cx.tcx.hir();
1307-
let parent_id = map.get_parent_node(expr.hir_id);
1308-
let parent_node = map.get(parent_id);
1309-
matches!(
1310-
parent_node,
1311-
Node::Expr(Expr {
1312-
kind: ExprKind::If(_, _, _),
1313-
..
1314-
})
1315-
)
1316-
}
1317-
13181303
// Finds the `#[must_use]` attribute, if any
13191304
pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
13201305
attrs.iter().find(|a| a.has_name(sym::must_use))

tests/ui/branches_sharing_code/shared_at_bottom.rs

+14
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,18 @@ fn fp_test() {
206206
}
207207
}
208208

209+
fn fp_if_let_issue7054() {
210+
// This shouldn't trigger the lint
211+
let string;
212+
let _x = if let true = true {
213+
""
214+
} else if true {
215+
string = "x".to_owned();
216+
&string
217+
} else {
218+
string = "y".to_owned();
219+
&string
220+
};
221+
}
222+
209223
fn main() {}

tests/ui/branches_sharing_code/shared_at_top.rs

+11
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,15 @@ fn check_if_same_than_else_mask() {
100100
}
101101
}
102102

103+
#[allow(clippy::vec_init_then_push)]
104+
fn pf_local_with_inferred_type_issue7053() {
105+
if true {
106+
let mut v = Vec::new();
107+
v.push(0);
108+
} else {
109+
let mut v = Vec::new();
110+
v.push("");
111+
};
112+
}
113+
103114
fn main() {}

util/gh-pages/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
opacity: 30%;
134134
}
135135

136-
p > code {
136+
:not(pre) > code {
137137
color: var(--inline-code-color);
138138
background-color: var(--inline-code-bg);
139139
}

0 commit comments

Comments
 (0)