matches: Restore match_type logic; add tests for these cases

This commit is contained in:
Georgy Komarov 2022-01-26 18:20:35 +03:00
parent 81015870df
commit 467a0bfdea
2 changed files with 52 additions and 19 deletions

View file

@ -5,7 +5,7 @@ use clippy_utils::diagnostics::{
use clippy_utils::macros::{is_panic, root_macro_call}; use clippy_utils::macros::{is_panic, root_macro_call};
use clippy_utils::source::{expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability}; use clippy_utils::source::{expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability};
use clippy_utils::sugg::Sugg; use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs};
use clippy_utils::visitors::is_local_used; use clippy_utils::visitors::is_local_used;
use clippy_utils::{ use clippy_utils::{
get_parent_expr, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild, meets_msrv, msrvs, 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
let ty = cx.typeck_results().expr_ty(ex); let ty = cx.typeck_results().expr_ty(ex);
if *ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id) { if *ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id) {
check_single_match_single_pattern(cx, ex, arms, expr, els); check_single_match_single_pattern(cx, ex, arms, expr, els);
check_single_match_opt_like(cx, ex, arms, expr, els); check_single_match_opt_like(cx, ex, arms, expr, ty, els);
} }
} }
} }
@ -830,11 +830,12 @@ fn report_single_match_single_pattern(
); );
} }
fn check_single_match_opt_like( fn check_single_match_opt_like<'a>(
cx: &LateContext<'_>, cx: &LateContext<'a>,
ex: &Expr<'_>, ex: &Expr<'_>,
arms: &[Arm<'_>], arms: &[Arm<'_>],
expr: &Expr<'_>, expr: &Expr<'_>,
ty: Ty<'a>,
els: Option<&Expr<'_>>, els: Option<&Expr<'_>>,
) { ) {
// list of candidate `Enum`s we know will never get any more members // list of candidate `Enum`s we know will never get any more members
@ -854,44 +855,50 @@ fn check_single_match_opt_like(
return; return;
} }
let mut paths = Vec::new(); let mut paths_and_types = Vec::new();
if !collect_pat_paths(&mut paths, arms[1].pat) { if !collect_pat_paths(&mut paths_and_types, cx, arms[1].pat, ty) {
return; return;
} }
let in_candidate_enum = |path: &String| -> bool { let in_candidate_enum = |path_info: &(String, &TyS<'_>)| -> bool {
for &(_, pat_path) in candidates { let (path, ty) = path_info;
if path == pat_path { for &(ty_path, pat_path) in candidates {
if path == pat_path && match_type(cx, ty, ty_path) {
return true; return true;
} }
} }
false false
}; };
if paths.iter().all(in_candidate_enum) { if paths_and_types.iter().all(in_candidate_enum) {
report_single_match_single_pattern(cx, ex, arms, expr, els); report_single_match_single_pattern(cx, ex, arms, expr, els);
} }
} }
/// Collects paths from the given paths. Returns true if the given pattern could be simplified, /// Collects paths and their types from the given patterns. Returns true if the given pattern could
/// false otherwise. /// be simplified, false otherwise.
fn collect_pat_paths(acc: &mut Vec<String>, pat: &Pat<'_>) -> bool { fn collect_pat_paths<'a>(acc: &mut Vec<(String, Ty<'a>)>, cx: &LateContext<'a>, pat: &Pat<'_>, ty: Ty<'a>) -> bool {
match pat.kind { match pat.kind {
PatKind::Wild => true, PatKind::Wild => true,
PatKind::Tuple(inner, _) => inner.iter().all(|p| collect_pat_paths(acc, p)), PatKind::Tuple(inner, _) => inner.iter().all(|p| {
let p_ty = cx.typeck_results().pat_ty(p);
collect_pat_paths(acc, cx, p, p_ty)
}),
PatKind::TupleStruct(ref path, ..) => { PatKind::TupleStruct(ref path, ..) => {
acc.push(rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| { let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
s.print_qpath(path, false); s.print_qpath(path, false);
})); });
acc.push((path, ty));
true true
}, },
PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => { PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => {
acc.push(ident.to_string()); acc.push((ident.to_string(), ty));
true true
}, },
PatKind::Path(ref path) => { PatKind::Path(ref path) => {
acc.push(rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| { let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
s.print_qpath(path, false); s.print_qpath(path, false);
})); });
acc.push((path, ty));
true true
}, },
_ => false, _ => false,

View file

@ -197,6 +197,32 @@ fn ranges() {
} }
} }
fn skip_type_aliases() {
enum OptionEx {
Some(i32),
None,
}
enum ResultEx {
Err(i32),
Ok(i32),
}
use OptionEx::{None, Some};
use ResultEx::{Err, Ok};
// don't lint
match Err(42) {
Ok(_) => dummy(),
Err(_) => (),
};
// don't lint
match Some(1i32) {
Some(_) => dummy(),
None => (),
};
}
macro_rules! single_match { macro_rules! single_match {
($num:literal) => { ($num:literal) => {
match $num { match $num {