Skip to content

Commit 8c78400

Browse files
committed
Fix clippy.
1 parent d01498a commit 8c78400

File tree

1 file changed

+65
-16
lines changed

1 file changed

+65
-16
lines changed

src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs

+65-16
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::REDUNDANT_PATTERN_MATCHING;
22
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::source::snippet;
44
use clippy_utils::sugg::Sugg;
5-
use clippy_utils::ty::needs_ordered_drop;
5+
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
66
use clippy_utils::visitors::any_temporaries_need_ordered_drop;
77
use clippy_utils::{higher, is_lang_ctor, is_trait_method, match_def_path, paths};
88
use if_chain::if_chain;
@@ -12,7 +12,7 @@ use rustc_hir::LangItem::{OptionNone, PollPending};
1212
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
1313
use rustc_lint::LateContext;
1414
use rustc_middle::ty::{self, subst::GenericArgKind, DefIdTree, Ty};
15-
use rustc_span::sym;
15+
use rustc_span::{sym, Symbol, def_id::DefId};
1616

1717
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
1818
if let Some(higher::WhileLet { let_pat, let_expr, .. }) = higher::WhileLet::hir(expr) {
@@ -75,9 +75,9 @@ fn find_sugg_for_if_let<'tcx>(
7575
("is_some()", op_ty)
7676
} else if Some(id) == lang_items.poll_ready_variant() {
7777
("is_ready()", op_ty)
78-
} else if match_def_path(cx, id, &paths::IPADDR_V4) {
78+
} else if is_pat_variant(cx, check_pat, qpath, &paths::IPADDR_V4, Item::Diag(sym!(IpAddr), sym!(V4))) {
7979
("is_ipv4()", op_ty)
80-
} else if match_def_path(cx, id, &paths::IPADDR_V6) {
80+
} else if is_pat_variant(cx, check_pat, qpath, &paths::IPADDR_V6, Item::Diag(sym!(IpAddr), sym!(V6))) {
8181
("is_ipv6()", op_ty)
8282
} else {
8383
return;
@@ -174,6 +174,7 @@ fn find_sugg_for_if_let<'tcx>(
174174

175175
pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: &Expr<'_>, arms: &[Arm<'_>]) {
176176
if arms.len() == 2 {
177+
let lang_items = cx.tcx.lang_items();
177178
let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind);
178179

179180
let found_good_method = match node_pair {
@@ -188,7 +189,9 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
188189
path_left,
189190
path_right,
190191
&paths::RESULT_OK,
192+
Item::Lang(lang_items.result_ok_variant()),
191193
&paths::RESULT_ERR,
194+
Item::Lang(lang_items.result_err_variant()),
192195
"is_ok()",
193196
"is_err()",
194197
)
@@ -199,7 +202,9 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
199202
path_left,
200203
path_right,
201204
&paths::IPADDR_V4,
205+
Item::Diag(sym!(IpAddr), sym!(V4)),
202206
&paths::IPADDR_V6,
207+
Item::Diag(sym!(IpAddr), sym!(V6)),
203208
"is_ipv4()",
204209
"is_ipv6()",
205210
)
@@ -213,13 +218,16 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
213218
if patterns.len() == 1 =>
214219
{
215220
if let PatKind::Wild = patterns[0].kind {
221+
216222
find_good_method_for_match(
217223
cx,
218224
arms,
219225
path_left,
220226
path_right,
221227
&paths::OPTION_SOME,
228+
Item::Lang(lang_items.option_some_variant()),
222229
&paths::OPTION_NONE,
230+
Item::Lang(lang_items.option_none_variant()),
223231
"is_some()",
224232
"is_none()",
225233
)
@@ -230,7 +238,9 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
230238
path_left,
231239
path_right,
232240
&paths::POLL_READY,
241+
Item::Lang(lang_items.poll_ready_variant()),
233242
&paths::POLL_PENDING,
243+
Item::Lang(lang_items.poll_pending_variant()),
234244
"is_ready()",
235245
"is_pending()",
236246
)
@@ -266,28 +276,67 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
266276
}
267277
}
268278

279+
#[derive(Clone, Copy)]
280+
enum Item {
281+
Lang(Option<DefId>),
282+
Diag(Symbol, Symbol),
283+
}
284+
285+
fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expected_path: &[&str], expected_item: Item) -> bool {
286+
let Some(id) = cx.typeck_results().qpath_res(path, pat.hir_id).opt_def_id() else { return false };
287+
288+
// TODO: Path matching can be removed when `IpAddr` is a diagnostic item.
289+
if match_def_path(cx, id, expected_path) {
290+
return true
291+
}
292+
293+
match expected_item {
294+
Item::Lang(expected_id) => {
295+
Some(cx.tcx.parent(id)) == expected_id
296+
},
297+
Item::Diag(expected_ty, expected_variant) => {
298+
let ty = cx.typeck_results().pat_ty(pat);
299+
300+
if is_type_diagnostic_item(cx, ty, expected_ty) {
301+
let variant = ty.ty_adt_def()
302+
.expect("struct pattern type is not an ADT")
303+
.variant_of_res(cx.qpath_res(path, pat.hir_id));
304+
305+
return variant.name == expected_variant
306+
}
307+
308+
false
309+
}
310+
}
311+
}
312+
269313
#[expect(clippy::too_many_arguments)]
270314
fn find_good_method_for_match<'a>(
271315
cx: &LateContext<'_>,
272316
arms: &[Arm<'_>],
273317
path_left: &QPath<'_>,
274318
path_right: &QPath<'_>,
275-
expected_left: &[&str],
276-
expected_right: &[&str],
319+
expected_path_left: &[&str],
320+
expected_item_left: Item,
321+
expected_path_right: &[&str],
322+
expected_item_right: Item,
277323
should_be_left: &'a str,
278324
should_be_right: &'a str,
279325
) -> Option<&'a str> {
280-
let left_id = cx
281-
.typeck_results()
282-
.qpath_res(path_left, arms[0].pat.hir_id)
283-
.opt_def_id()?;
284-
let right_id = cx
285-
.typeck_results()
286-
.qpath_res(path_right, arms[1].pat.hir_id)
287-
.opt_def_id()?;
288-
let body_node_pair = if match_def_path(cx, left_id, expected_left) && match_def_path(cx, right_id, expected_right) {
326+
let pat_left = arms[0].pat;
327+
let pat_right = arms[1].pat;
328+
329+
let body_node_pair = if (
330+
is_pat_variant(cx, pat_left, path_left, expected_path_left, expected_item_left)
331+
) && (
332+
is_pat_variant(cx, pat_right, path_right, expected_path_right, expected_item_right)
333+
) {
289334
(&arms[0].body.kind, &arms[1].body.kind)
290-
} else if match_def_path(cx, right_id, expected_left) && match_def_path(cx, right_id, expected_right) {
335+
} else if (
336+
is_pat_variant(cx, pat_left, path_left, expected_path_right, expected_item_right)
337+
) && (
338+
is_pat_variant(cx, pat_right, path_right, expected_path_left, expected_item_left)
339+
) {
291340
(&arms[1].body.kind, &arms[0].body.kind)
292341
} else {
293342
return None;

0 commit comments

Comments
 (0)