Skip to content

Commit 467a0bf

Browse files
committed
matches: Restore match_type logic; add tests for these cases
1 parent 8101587 commit 467a0bf

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

clippy_lints/src/matches.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use clippy_utils::diagnostics::{
55
use clippy_utils::macros::{is_panic, root_macro_call};
66
use clippy_utils::source::{expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability};
77
use clippy_utils::sugg::Sugg;
8-
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs};
8+
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs};
99
use clippy_utils::visitors::is_local_used;
1010
use clippy_utils::{
1111
get_parent_expr, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild, meets_msrv, msrvs,
@@ -741,7 +741,7 @@ fn check_single_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp
741741
let ty = cx.typeck_results().expr_ty(ex);
742742
if *ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id) {
743743
check_single_match_single_pattern(cx, ex, arms, expr, els);
744-
check_single_match_opt_like(cx, ex, arms, expr, els);
744+
check_single_match_opt_like(cx, ex, arms, expr, ty, els);
745745
}
746746
}
747747
}
@@ -830,11 +830,12 @@ fn report_single_match_single_pattern(
830830
);
831831
}
832832

833-
fn check_single_match_opt_like(
834-
cx: &LateContext<'_>,
833+
fn check_single_match_opt_like<'a>(
834+
cx: &LateContext<'a>,
835835
ex: &Expr<'_>,
836836
arms: &[Arm<'_>],
837837
expr: &Expr<'_>,
838+
ty: Ty<'a>,
838839
els: Option<&Expr<'_>>,
839840
) {
840841
// list of candidate `Enum`s we know will never get any more members
@@ -854,44 +855,50 @@ fn check_single_match_opt_like(
854855
return;
855856
}
856857

857-
let mut paths = Vec::new();
858-
if !collect_pat_paths(&mut paths, arms[1].pat) {
858+
let mut paths_and_types = Vec::new();
859+
if !collect_pat_paths(&mut paths_and_types, cx, arms[1].pat, ty) {
859860
return;
860861
}
861862

862-
let in_candidate_enum = |path: &String| -> bool {
863-
for &(_, pat_path) in candidates {
864-
if path == pat_path {
863+
let in_candidate_enum = |path_info: &(String, &TyS<'_>)| -> bool {
864+
let (path, ty) = path_info;
865+
for &(ty_path, pat_path) in candidates {
866+
if path == pat_path && match_type(cx, ty, ty_path) {
865867
return true;
866868
}
867869
}
868870
false
869871
};
870-
if paths.iter().all(in_candidate_enum) {
872+
if paths_and_types.iter().all(in_candidate_enum) {
871873
report_single_match_single_pattern(cx, ex, arms, expr, els);
872874
}
873875
}
874876

875-
/// Collects paths from the given paths. Returns true if the given pattern could be simplified,
876-
/// false otherwise.
877-
fn collect_pat_paths(acc: &mut Vec<String>, pat: &Pat<'_>) -> bool {
877+
/// Collects paths and their types from the given patterns. Returns true if the given pattern could
878+
/// be simplified, false otherwise.
879+
fn collect_pat_paths<'a>(acc: &mut Vec<(String, Ty<'a>)>, cx: &LateContext<'a>, pat: &Pat<'_>, ty: Ty<'a>) -> bool {
878880
match pat.kind {
879881
PatKind::Wild => true,
880-
PatKind::Tuple(inner, _) => inner.iter().all(|p| collect_pat_paths(acc, p)),
882+
PatKind::Tuple(inner, _) => inner.iter().all(|p| {
883+
let p_ty = cx.typeck_results().pat_ty(p);
884+
collect_pat_paths(acc, cx, p, p_ty)
885+
}),
881886
PatKind::TupleStruct(ref path, ..) => {
882-
acc.push(rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
887+
let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
883888
s.print_qpath(path, false);
884-
}));
889+
});
890+
acc.push((path, ty));
885891
true
886892
},
887893
PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => {
888-
acc.push(ident.to_string());
894+
acc.push((ident.to_string(), ty));
889895
true
890896
},
891897
PatKind::Path(ref path) => {
892-
acc.push(rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
898+
let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
893899
s.print_qpath(path, false);
894-
}));
900+
});
901+
acc.push((path, ty));
895902
true
896903
},
897904
_ => false,

tests/ui/single_match.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,32 @@ fn ranges() {
197197
}
198198
}
199199

200+
fn skip_type_aliases() {
201+
enum OptionEx {
202+
Some(i32),
203+
None,
204+
}
205+
enum ResultEx {
206+
Err(i32),
207+
Ok(i32),
208+
}
209+
210+
use OptionEx::{None, Some};
211+
use ResultEx::{Err, Ok};
212+
213+
// don't lint
214+
match Err(42) {
215+
Ok(_) => dummy(),
216+
Err(_) => (),
217+
};
218+
219+
// don't lint
220+
match Some(1i32) {
221+
Some(_) => dummy(),
222+
None => (),
223+
};
224+
}
225+
200226
macro_rules! single_match {
201227
($num:literal) => {
202228
match $num {

0 commit comments

Comments
 (0)