mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 21:23:56 +00:00
matches: Restore match_type
logic; add tests for these cases
This commit is contained in:
parent
81015870df
commit
467a0bfdea
2 changed files with 52 additions and 19 deletions
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue