Skip to content

Commit b0e9bff

Browse files
committed
PR suggestions and removing utils::parent_node_is_if_expr
1 parent 3b28745 commit b0e9bff

File tree

6 files changed

+40
-96
lines changed

6 files changed

+40
-96
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

+28-15
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,15 +295,19 @@ fn lint_same_then_else<'tcx>(
290295
}
291296
}
292297

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> {
302311
let mut start_eq = usize::MAX;
303312
let mut end_eq = usize::MAX;
304313
let mut expr_eq = true;
@@ -308,7 +317,7 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize,
308317

309318
// `SpanlessEq` now keeps track of the locals and is therefore context sensitive clippy#6752.
310319
// 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);
312321
let mut evaluator = evaluator.inter_expr();
313322

314323
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,
340349
"same as this",
341350
);
342351

343-
return (0, 0, false);
352+
return None;
344353
}
345354
}
346355

@@ -360,7 +369,11 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize,
360369
end_eq = min_block_size - start_eq;
361370
}
362371

363-
(start_eq, end_eq, expr_eq)
372+
Some(BlockEqual {
373+
start_eq,
374+
end_eq,
375+
expr_eq,
376+
})
364377
}
365378

366379
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::{match_qpath, meets_msrv, parent_node_is_if_expr};
3+
use clippy_utils::{is_else_clause, match_qpath, meets_msrv};
44
use if_chain::if_chain;
55
use rustc_hir::{Expr, ExprKind};
66
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -67,7 +67,7 @@ impl LateLintPass<'_> for IfThenSomeElseNone {
6767
}
6868

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

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

+6-44
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::consts::{constant_context, constant_simple};
22
use crate::differing_macro_contexts;
33
use crate::source::snippet_opt;
4-
use if_chain::if_chain;
54
use rustc_ast::ast::InlineAsmTemplatePiece;
65
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
76
use rustc_hir::def::Res;
@@ -30,30 +29,6 @@ pub struct SpanlessEq<'a, 'tcx> {
3029
maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>,
3130
allow_side_effects: bool,
3231
expr_fallback: Option<Box<dyn FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a>>,
33-
/// This adds an additional type comparison to locals that insures that even the
34-
/// inferred of the value is the same.
35-
///
36-
/// **Example**
37-
/// * Context 1
38-
/// ```ignore
39-
/// let vec = Vec::new();
40-
/// vec.push("A string");
41-
/// ```
42-
///
43-
/// * Context 2
44-
/// ```ignore
45-
/// let vec = Vec::new();
46-
/// vec.push(0); // An integer
47-
/// ```
48-
///
49-
/// Only comparing the first local definition would usually return that they are
50-
/// equal, since they are identical. However, they are different due to the context
51-
/// as they have different inferred types.
52-
///
53-
/// This option enables or disables the specific check of the inferred type.
54-
///
55-
/// Note: This check will only be done if `self.maybe_typeck_results` is `Some()`.
56-
check_inferred_local_types: bool,
5732
}
5833

5934
impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
@@ -63,7 +38,6 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
6338
maybe_typeck_results: cx.maybe_typeck_results(),
6439
allow_side_effects: true,
6540
expr_fallback: None,
66-
check_inferred_local_types: false,
6741
}
6842
}
6943

@@ -82,13 +56,6 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
8256
}
8357
}
8458

85-
pub fn enable_check_inferred_local_types(self) -> Self {
86-
Self {
87-
check_inferred_local_types: true,
88-
..self
89-
}
90-
}
91-
9259
/// Use this method to wrap comparisons that may involve inter-expression context.
9360
/// See `self.locals`.
9461
pub fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> {
@@ -129,17 +96,12 @@ impl HirEqInterExpr<'_, '_, '_> {
12996
pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
13097
match (&left.kind, &right.kind) {
13198
(&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => {
132-
// See `SpanlessEq::check_inferred_local_types` for an explication of this check
133-
if_chain! {
134-
if l.ty.is_none() && r.ty.is_none();
135-
if self.inner.check_inferred_local_types;
136-
if let Some(tcx) = self.inner.maybe_typeck_results;
137-
138-
// Check the inferred types
139-
let l_ty = tcx.pat_ty(&l.pat);
140-
let r_ty = tcx.pat_ty(&r.pat);
141-
if l_ty != r_ty;
142-
then {
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) {
143105
return false;
144106
}
145107
}

clippy_utils/src/lib.rs

-31
Original file line numberDiff line numberDiff line change
@@ -1189,37 +1189,6 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
11891189
(conds, blocks)
11901190
}
11911191

1192-
/// This function returns true if the given expression is the `else` or `if else` part of an if
1193-
/// statement
1194-
pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
1195-
let map = cx.tcx.hir();
1196-
let parent_id = map.get_parent_node(expr.hir_id);
1197-
let parent_node = map.get(parent_id);
1198-
1199-
// Check for `if`
1200-
if_chain! {
1201-
if let Node::Expr(expr) = parent_node;
1202-
if let ExprKind::If(_, _, _) = expr.kind;
1203-
then {
1204-
return true;
1205-
}
1206-
}
1207-
1208-
// Check for `if let`
1209-
if_chain! {
1210-
if let Node::Arm(arm) = parent_node;
1211-
let arm_parent_id = map.get_parent_node(arm.hir_id);
1212-
let arm_parent_node = map.get(arm_parent_id);
1213-
if let Node::Expr(expr) = arm_parent_node;
1214-
if let ExprKind::Match(_, _, MatchSource::IfLetDesugar { .. }) = expr.kind;
1215-
then {
1216-
return true;
1217-
}
1218-
}
1219-
1220-
false
1221-
}
1222-
12231192
// Finds the `#[must_use]` attribute, if any
12241193
pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
12251194
attrs.iter().find(|a| a.has_name(sym::must_use))

0 commit comments

Comments
 (0)