From 8a83fe326a33d1ccad395f3911fc033d2b261e7d Mon Sep 17 00:00:00 2001 From: hahohihu Date: Mon, 6 Dec 2021 16:49:17 -0500 Subject: [PATCH 01/47] init + tests --- CHANGELOG.md | 1 + clippy_lints/src/lib.register_all.rs | 1 + clippy_lints/src/lib.register_lints.rs | 1 + clippy_lints/src/lib.register_style.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/single_field_pattern.rs | 25 ++++ tests/ui/single_field_pattern.rs | 168 +++++++++++++++++++++++ 7 files changed, 199 insertions(+) create mode 100644 clippy_lints/src/single_field_pattern.rs create mode 100644 tests/ui/single_field_pattern.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 157ea0c963af..c6c2ab9dc4f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3140,6 +3140,7 @@ Released 2018-09-13 [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern [`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop +[`single_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_field_pattern [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs index b7b5f059de6f..cfb303c021d6 100644 --- a/clippy_lints/src/lib.register_all.rs +++ b/clippy_lints/src/lib.register_all.rs @@ -252,6 +252,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), LintId::of(serde_api::SERDE_API_MISUSE), LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), + LintId::of(single_field_pattern::SINGLE_FIELD_PATTERN), LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs index bb159e50373c..ea236531da1f 100644 --- a/clippy_lints/src/lib.register_lints.rs +++ b/clippy_lints/src/lib.register_lints.rs @@ -433,6 +433,7 @@ store.register_lints(&[ shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, + single_field_pattern::SINGLE_FIELD_PATTERN, size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT, slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, stable_sort_primitive::STABLE_SORT_PRIMITIVE, diff --git a/clippy_lints/src/lib.register_style.rs b/clippy_lints/src/lib.register_style.rs index ea87e7e7a736..90f8c05a5832 100644 --- a/clippy_lints/src/lib.register_style.rs +++ b/clippy_lints/src/lib.register_style.rs @@ -99,6 +99,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(returns::NEEDLESS_RETURN), LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), + LintId::of(single_field_pattern::SINGLE_FIELD_PATTERN), LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), LintId::of(try_err::TRY_ERR), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bd9710ec4075..c57c6a25176e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -349,6 +349,7 @@ mod semicolon_if_nothing_returned; mod serde_api; mod shadow; mod single_component_path_imports; +mod single_field_pattern; mod size_of_in_element_count; mod slow_vector_initialization; mod stable_sort_primitive; @@ -853,6 +854,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray)); store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes)); store.register_late_pass(|| Box::new(needless_late_init::NeedlessLateInit)); + store.register_late_pass(|| Box::new(single_field_pattern::SingleFieldPattern)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs new file mode 100644 index 000000000000..51b4f34fba1d --- /dev/null +++ b/clippy_lints/src/single_field_pattern.rs @@ -0,0 +1,25 @@ +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// + /// ### Why is this bad? + /// + /// ### Example + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + #[clippy::version = "1.59.0"] + pub SINGLE_FIELD_PATTERN, + style, + "default lint description" +} +declare_lint_pass!(SingleFieldPattern => [SINGLE_FIELD_PATTERN]); + +impl LateLintPass<'_> for SingleFieldPattern {} diff --git a/tests/ui/single_field_pattern.rs b/tests/ui/single_field_pattern.rs new file mode 100644 index 000000000000..8b40f9aecc3b --- /dev/null +++ b/tests/ui/single_field_pattern.rs @@ -0,0 +1,168 @@ +#![warn(clippy::single_field_pattern)] + +struct Struct { + field1: Option, + field2: Option, +} + +fn lint_struct(struct1: Struct) { + let Struct { field1, .. } = struct1; + let Struct { field1, field2: _ } = struct1; + match struct1 { + Struct { field1: Some(n), .. } if n >= 50 => {}, + Struct { field1: None, .. } => {}, + _ => {}, + } + match struct1 { + Struct { field1: Some(1), .. } => {}, + Struct { field1: Some(2), .. } => {}, + Struct { field1: None, .. } => {}, + _ => {}, + } + match struct1 { + Struct { + field1: Some(_) | None, .. + } => {}, + } + while let Struct { field1: Some(5), .. } = struct1 {} +} + +fn ok_struct(struct1: Struct) { + let Struct { field1, field2, .. } = struct1; + let Struct { field1, field2 } = struct1; + match struct1 { + Struct { + field1: Some(1), + field2: _, + } => {}, + Struct { + field1: _, + field2: Some(1), + } => {}, + _ => {}, + } + match struct1 { + Struct { field1: Some(1), .. } => {}, + Struct { + field1: _, + field2: Some(1), + } => {}, + _ => {}, + } + let s @ Struct { field1, .. } = struct1; +} + +struct Tuple(Option, Option); + +fn lint_tuple_struct(tuple: Tuple) { + if let Tuple(Some(x), _) = tuple {} + if let Tuple(_, Some(y)) = tuple {} + match tuple { + Tuple(Some(1), ..) => {}, + Tuple(Some(2), ..) => {}, + Tuple(a, ..) => {}, + } + match tuple { + Tuple(.., Some(1)) => {}, + Tuple(.., Some(2)) => {}, + Tuple(.., None) => {}, + _ => {}, + } + match tuple { + Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, + Tuple(a, ..) => {}, + } +} + +fn ok_tuple_struct(tuple: Tuple) { + if let Tuple(Some(1), two) = tuple {} + if let Tuple(one, Some(1)) = tuple {} + match tuple { + Tuple(Some(1), _) => {}, + Tuple(_, Some(1)) => {}, + _ => {}, + } + match tuple { + Tuple(Some(1), ..) => {}, + Tuple(.., Some(1)) => {}, + _ => {}, + } + let t @ Tuple(_, two) = tuple; +} + +fn lint_tuple(tuple: (Option, Option)) { + if let (Some(z), _) = tuple {} + if let (_, Some(n)) = tuple {} + match tuple { + (Some(1), ..) => {}, + (Some(2), ..) => {}, + (a, ..) => {}, + } + match tuple { + (.., Some(1)) => {}, + (.., Some(2)) => {}, + (.., None) => {}, + _ => {}, + } + match tuple { + (Some(1) | Some(42) | Some(6082), ..) => {}, + (a, ..) => {}, + } +} + +fn ok_tuple(tuple: (Option, Option)) { + if let (None, two) = tuple {} + if let (one, Some(1)) = tuple {} + match tuple { + (Some(1), _) => {}, + (_, Some(1)) => {}, + _ => {}, + } + match tuple { + (Some(1), ..) => {}, + (.., Some(1)) => {}, + _ => {}, + } + let t @ (one, two) = tuple; +} + +fn lint_array(array: [i32; 3]) { + match array { + [.., 1 | 2] => {}, + [.., x @ 3] => {}, + [.., r @ 20..=65] => {}, + [.., e] => {}, + } + if let [5, ..] = array {} +} + +fn ok_slice(slice: &[i32]) { + // slices may panic if indexed, but will never panic + // in a pattern since they're forced to check if they're empty + match slice { + [.., x] => {}, + [] => {}, + } + if let [x, ..] = slice {} +} + +enum Enum { + Enum(Option, Option), + OtherEnum, +} + +fn ok_enum(enum1: Enum) { + // Should never touch enums for this lint + // since there's no way to access a field directly + if let Enum::Enum(one, _) = enum1 {} + match enum1 { + Enum::Enum(one, ..) => {}, + Enum::Enum(_, _) => {}, + Enum::OtherEnum => {}, + } +} + +// This results in less in-scope variables, so I figure it's ok +fn ok_fn_pattern(Struct { field1, .. }: Struct) {} + +fn main() {} From e75127c87410a6d760a5c044d682bd08b15f74f3 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 11 Dec 2021 22:11:31 -0500 Subject: [PATCH 02/47] poc - need to add blank fields; suggestion --- clippy_lints/src/single_field_pattern.rs | 149 ++++++++++++++++++++++- tests/ui/single_field_pattern.rs | 110 +++++++++-------- 2 files changed, 206 insertions(+), 53 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index 51b4f34fba1d..36022d5152db 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -1,6 +1,12 @@ +#![allow(rustc::usage_of_ty_tykind)] + +use clippy_utils::{diagnostics::span_lint, higher::IfLetOrMatch, higher::WhileLet}; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{symbol::Ident, MultiSpan}; +use std::iter::once; declare_clippy_lint! { /// ### What it does @@ -22,4 +28,145 @@ declare_clippy_lint! { } declare_lint_pass!(SingleFieldPattern => [SINGLE_FIELD_PATTERN]); -impl LateLintPass<'_> for SingleFieldPattern {} +#[derive(PartialEq, Eq, Debug, Clone)] +enum Fields { + Id(Ident), + Index(usize), + Unused, +} + +impl Fields { + // Todo - auto-fix - I'll need to add span and strings into SingleField + fn lint(self, cx: &LateContext<'tcx>, span: impl Into) { + span_lint( + cx, + SINGLE_FIELD_PATTERN, + span, + "pattern matching just to get a single field", + ); + } +} + +impl From for Fields { + fn from(id: Ident) -> Self { + Fields::Id(id) + } +} + +impl From for Fields { + fn from(id: usize) -> Self { + Fields::Index(id) + } +} + +fn get_the_one>(pat: impl Iterator)>) -> Option { + let mut iter = pat.filter(|&(_, pat)| !matches!(pat.kind, PatKind::Wild)).map(|t| t.0); + let the_one = iter.next(); // TODO: this also eliminates blank patterns, e.g. Struct { .. } - as silly as it is + if let None = iter.next() { + the_one.map(|id| id.into()).or(Some(Fields::Unused)) + } else { + None + } +} + +fn single_struct(pat: &PatKind<'hir>) -> Option { + if let PatKind::Struct(_, inner_pats, _) = pat { + if let field @ Some(Fields::Id(_)) = get_the_one(inner_pats.iter().map(|field| (field.ident, field.pat))) { + return field; + } + } + None +} + +fn single_tuple(pat: &PatKind<'hir>) -> Option { + if let PatKind::Tuple(inner_pats, leap) | PatKind::TupleStruct(_, inner_pats, leap) = pat { + if let field @ Some(Fields::Index(index)) = get_the_one((*inner_pats).iter().enumerate()) { + // Skip (.., x) - the meaning of let (.., x) = t and t.n are different + if (*leap).map_or(true, |leap_index| leap_index > index) { + return field; + } + } + } + None +} + +fn single_slice(pat: &PatKind<'hir>) -> Option { + if let PatKind::Slice(before, dots, after) = pat { + if let field @ Some(Fields::Index(_)) = get_the_one(before.iter().enumerate()) { + if dots.is_none() || get_the_one(after.iter().enumerate()).is_none() { + return field; + } + } + } + None +} + +fn walk_until_single_field_leaf<'hir>( + patterns: impl Iterator>, + get_leaf: &impl Fn(&PatKind<'hir>) -> Option, +) -> Option { + let mut fields = patterns + .map(|pat| match &pat.kind { + PatKind::Or(pats) => walk_until_single_field_leaf(pats.iter(), get_leaf), + PatKind::Wild => Some(Fields::Unused), + p => get_leaf(p), + }) + .filter(|field| *field != Some(Fields::Unused)); + if let Some(the_one) = fields.next() { + if fields.all(|other| other == the_one) { + return the_one; + } + } + None +} + +fn find_single_pattern<'hir>(ty: &ty::TyKind<'_>, patterns: impl Iterator>) -> Option { + match ty { + ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.variants.raw.len() == 1 => { + walk_until_single_field_leaf(patterns, &|kind| single_struct(kind).or_else(|| single_tuple(kind))) + }, + ty::TyKind::Array(..) => walk_until_single_field_leaf(patterns, &|kind| single_slice(kind)), + ty::TyKind::Tuple(..) => walk_until_single_field_leaf(patterns, &|kind| single_tuple(kind)), + _ => None, + } +} + +fn expr_helper<'hir>(cx: &LateContext<'_>, scrutinee: &Expr<'_>, patterns: impl Iterator>) { + find_single_pattern(cx.typeck_results().expr_ty(scrutinee).kind(), patterns) + .map(|pattern| pattern.lint(cx, scrutinee.span)); +} + +impl LateLintPass<'_> for SingleFieldPattern { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if expr.span.from_expansion() { + return; + } + match IfLetOrMatch::parse(cx, expr) { + Some(IfLetOrMatch::Match(scrutinee, arms, MatchSource::Normal)) => { + expr_helper(cx, scrutinee, arms.iter().map(|arm| arm.pat)) + }, + Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => expr_helper(cx, scrutinee, once(pat)), + _ => { + if let Some(WhileLet { let_pat, let_expr, .. }) = WhileLet::hir(expr) { + expr_helper(cx, let_expr, once(let_pat)) + } + }, + }; + } + + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'tcx>) { + if stmt.span.from_expansion() { + return; + } + if let StmtKind::Local(Local { pat, ty, init, .. }) = stmt.kind { + let scrut_type = if let Some(t) = *ty { + cx.typeck_results().node_type(t.hir_id).kind() + } else if let Some(e) = init { + cx.typeck_results().expr_ty(e).kind() + } else { + return; + }; + find_single_pattern(scrut_type, once(*pat)).map(|field| field.lint(cx, stmt.span)); + } + } +} diff --git a/tests/ui/single_field_pattern.rs b/tests/ui/single_field_pattern.rs index 8b40f9aecc3b..b95aa41e5973 100644 --- a/tests/ui/single_field_pattern.rs +++ b/tests/ui/single_field_pattern.rs @@ -1,11 +1,11 @@ #![warn(clippy::single_field_pattern)] - struct Struct { field1: Option, field2: Option, } fn lint_struct(struct1: Struct) { + let Struct { .. } = struct1; let Struct { field1, .. } = struct1; let Struct { field1, field2: _ } = struct1; match struct1 { @@ -13,6 +13,11 @@ fn lint_struct(struct1: Struct) { Struct { field1: None, .. } => {}, _ => {}, } + match struct1 { + Struct { field1: Some(n), .. } if n >= 50 => {}, + Struct { .. } => {}, + _ => {}, + } match struct1 { Struct { field1: Some(1), .. } => {}, Struct { field1: Some(2), .. } => {}, @@ -27,6 +32,46 @@ fn lint_struct(struct1: Struct) { while let Struct { field1: Some(5), .. } = struct1 {} } +struct Tuple(Option, Option); + +fn lint_tuple_struct(tuple: Tuple) { + if let Tuple(Some(x), _) = tuple {} + if let Tuple(_, Some(y)) = tuple {} + match tuple { + Tuple(Some(1), ..) => {}, + Tuple(Some(2), ..) => {}, + Tuple(a, ..) => {}, + } + match tuple { + Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, + Tuple(a, ..) => {}, + } +} + +fn lint_tuple(tuple: (Option, Option)) { + if let (Some(z), _) = tuple {} + if let (_, Some(n)) = tuple {} + match tuple { + (Some(1), ..) => {}, + (Some(2), ..) => {}, + (a, ..) => {}, + } + match tuple { + (Some(1) | Some(42) | Some(6082), ..) => {}, + (a, ..) => {}, + } +} + +fn lint_array(array: [i32; 3]) { + match array { + [1 | 2, ..] => {}, + [x @ 3, ..] => {}, + [r @ 20..=65, ..] => {}, + [e, ..] => {}, + } + if let [5, ..] = array {} +} + fn ok_struct(struct1: Struct) { let Struct { field1, field2, .. } = struct1; let Struct { field1, field2 } = struct1; @@ -52,28 +97,6 @@ fn ok_struct(struct1: Struct) { let s @ Struct { field1, .. } = struct1; } -struct Tuple(Option, Option); - -fn lint_tuple_struct(tuple: Tuple) { - if let Tuple(Some(x), _) = tuple {} - if let Tuple(_, Some(y)) = tuple {} - match tuple { - Tuple(Some(1), ..) => {}, - Tuple(Some(2), ..) => {}, - Tuple(a, ..) => {}, - } - match tuple { - Tuple(.., Some(1)) => {}, - Tuple(.., Some(2)) => {}, - Tuple(.., None) => {}, - _ => {}, - } - match tuple { - Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, - Tuple(a, ..) => {}, - } -} - fn ok_tuple_struct(tuple: Tuple) { if let Tuple(Some(1), two) = tuple {} if let Tuple(one, Some(1)) = tuple {} @@ -87,27 +110,13 @@ fn ok_tuple_struct(tuple: Tuple) { Tuple(.., Some(1)) => {}, _ => {}, } - let t @ Tuple(_, two) = tuple; -} - -fn lint_tuple(tuple: (Option, Option)) { - if let (Some(z), _) = tuple {} - if let (_, Some(n)) = tuple {} - match tuple { - (Some(1), ..) => {}, - (Some(2), ..) => {}, - (a, ..) => {}, - } match tuple { - (.., Some(1)) => {}, - (.., Some(2)) => {}, - (.., None) => {}, + Tuple(.., Some(1)) => {}, + Tuple(.., Some(2)) => {}, + Tuple(.., None) => {}, _ => {}, } - match tuple { - (Some(1) | Some(42) | Some(6082), ..) => {}, - (a, ..) => {}, - } + let t @ Tuple(_, two) = tuple; } fn ok_tuple(tuple: (Option, Option)) { @@ -118,6 +127,12 @@ fn ok_tuple(tuple: (Option, Option)) { (_, Some(1)) => {}, _ => {}, } + match tuple { + (.., Some(1)) => {}, + (.., Some(2)) => {}, + (.., None) => {}, + _ => {}, + } match tuple { (Some(1), ..) => {}, (.., Some(1)) => {}, @@ -126,14 +141,8 @@ fn ok_tuple(tuple: (Option, Option)) { let t @ (one, two) = tuple; } -fn lint_array(array: [i32; 3]) { - match array { - [.., 1 | 2] => {}, - [.., x @ 3] => {}, - [.., r @ 20..=65] => {}, - [.., e] => {}, - } - if let [5, ..] = array {} +fn ok_array(array: [i32; 555]) { + if let [.., 209, _] = array {} } fn ok_slice(slice: &[i32]) { @@ -162,7 +171,4 @@ fn ok_enum(enum1: Enum) { } } -// This results in less in-scope variables, so I figure it's ok -fn ok_fn_pattern(Struct { field1, .. }: Struct) {} - fn main() {} From de0c847a7966b7f14f1c0b7c73ddcb992330cf06 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 11 Dec 2021 22:40:10 -0500 Subject: [PATCH 03/47] handle blank fields --- clippy_lints/src/single_field_pattern.rs | 55 ++++++++++++++---------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index 36022d5152db..c21e5284696f 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -28,7 +28,7 @@ declare_clippy_lint! { } declare_lint_pass!(SingleFieldPattern => [SINGLE_FIELD_PATTERN]); -#[derive(PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone, Copy)] enum Fields { Id(Ident), Index(usize), @@ -37,7 +37,7 @@ enum Fields { impl Fields { // Todo - auto-fix - I'll need to add span and strings into SingleField - fn lint(self, cx: &LateContext<'tcx>, span: impl Into) { + fn lint(self, cx: &LateContext<'_>, span: impl Into) { span_lint( cx, SINGLE_FIELD_PATTERN, @@ -62,40 +62,48 @@ impl From for Fields { fn get_the_one>(pat: impl Iterator)>) -> Option { let mut iter = pat.filter(|&(_, pat)| !matches!(pat.kind, PatKind::Wild)).map(|t| t.0); let the_one = iter.next(); // TODO: this also eliminates blank patterns, e.g. Struct { .. } - as silly as it is - if let None = iter.next() { + if iter.next().is_none() { the_one.map(|id| id.into()).or(Some(Fields::Unused)) } else { None } } -fn single_struct(pat: &PatKind<'hir>) -> Option { - if let PatKind::Struct(_, inner_pats, _) = pat { - if let field @ Some(Fields::Id(_)) = get_the_one(inner_pats.iter().map(|field| (field.ident, field.pat))) { - return field; - } +fn single_struct(pat: &PatKind<'_>) -> Option { + match pat { + PatKind::Struct(_, pats, _) => get_the_one(pats.iter().map(|field| (field.ident, field.pat))), + PatKind::TupleStruct(_, pats, leap) => single_tuple_inner(pats, leap), + _ => None, } - None } -fn single_tuple(pat: &PatKind<'hir>) -> Option { - if let PatKind::Tuple(inner_pats, leap) | PatKind::TupleStruct(_, inner_pats, leap) = pat { - if let field @ Some(Fields::Index(index)) = get_the_one((*inner_pats).iter().enumerate()) { +fn single_tuple_inner(pats: &&[Pat<'_>], leap: &Option) -> Option { + match get_the_one((*pats).iter().enumerate()) { + field @ Some(Fields::Index(index)) => { // Skip (.., x) - the meaning of let (.., x) = t and t.n are different if (*leap).map_or(true, |leap_index| leap_index > index) { - return field; + field + } else { + None } - } + }, + field @ Some(Fields::Unused) => field, + _ => None, } - None } -fn single_slice(pat: &PatKind<'hir>) -> Option { +fn single_tuple(pat: &PatKind<'_>) -> Option { + if let PatKind::Tuple(pats, leap) = pat { + single_tuple_inner(pats, leap) + } else { + None + } +} + +fn single_slice(pat: &PatKind<'_>) -> Option { if let PatKind::Slice(before, dots, after) = pat { - if let field @ Some(Fields::Index(_)) = get_the_one(before.iter().enumerate()) { - if dots.is_none() || get_the_one(after.iter().enumerate()).is_none() { - return field; - } + if dots.is_none() || after.len() == 0 { + return get_the_one(before.iter().enumerate()); } } None @@ -114,10 +122,13 @@ fn walk_until_single_field_leaf<'hir>( .filter(|field| *field != Some(Fields::Unused)); if let Some(the_one) = fields.next() { if fields.all(|other| other == the_one) { - return the_one; + the_one + } else { + None } + } else { + Some(Fields::Unused) } - None } fn find_single_pattern<'hir>(ty: &ty::TyKind<'_>, patterns: impl Iterator>) -> Option { From 46ad2ab621f07c658b8aedbff84b581163436801 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sun, 12 Dec 2021 09:25:58 -0500 Subject: [PATCH 04/47] pass function directly --- clippy_lints/src/single_field_pattern.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index c21e5284696f..0093213ae7b9 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -134,10 +134,10 @@ fn walk_until_single_field_leaf<'hir>( fn find_single_pattern<'hir>(ty: &ty::TyKind<'_>, patterns: impl Iterator>) -> Option { match ty { ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.variants.raw.len() == 1 => { - walk_until_single_field_leaf(patterns, &|kind| single_struct(kind).or_else(|| single_tuple(kind))) + walk_until_single_field_leaf(patterns, &single_struct) }, - ty::TyKind::Array(..) => walk_until_single_field_leaf(patterns, &|kind| single_slice(kind)), - ty::TyKind::Tuple(..) => walk_until_single_field_leaf(patterns, &|kind| single_tuple(kind)), + ty::TyKind::Array(..) => walk_until_single_field_leaf(patterns, &single_slice), + ty::TyKind::Tuple(..) => walk_until_single_field_leaf(patterns, &single_tuple), _ => None, } } From eff7948a02923cc4fe93e1e1cab01646fca68e6e Mon Sep 17 00:00:00 2001 From: hahohihu Date: Tue, 14 Dec 2021 20:51:41 -0500 Subject: [PATCH 05/47] propogate spans upwards --- clippy_lints/src/single_field_pattern.rs | 89 +++++++++++++++--------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index 0093213ae7b9..dfe59b2f63a3 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -5,7 +5,7 @@ use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{symbol::Ident, MultiSpan}; +use rustc_span::{symbol::Ident, MultiSpan, Span}; use std::iter::once; declare_clippy_lint! { @@ -28,12 +28,24 @@ declare_clippy_lint! { } declare_lint_pass!(SingleFieldPattern => [SINGLE_FIELD_PATTERN]); -#[derive(PartialEq, Eq, Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy)] enum Fields { - Id(Ident), - Index(usize), + Id(Ident, Span), + Index(usize, Span), Unused, } +use Fields::*; + +impl PartialEq for Fields { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Id(id1, ..), Id(id2, ..)) => id1 == id2, + (Index(index1, ..), Index(index2, ..)) => index1 == index2, + (Unused, Unused) => true, + _ => false, + } + } +} impl Fields { // Todo - auto-fix - I'll need to add span and strings into SingleField @@ -47,49 +59,57 @@ impl Fields { } } -impl From for Fields { - fn from(id: Ident) -> Self { - Fields::Id(id) - } -} - -impl From for Fields { - fn from(id: usize) -> Self { - Fields::Index(id) +fn get_one_index(pats: &[Pat<'a>]) -> Option { + let mut iter = pats.iter().enumerate(); + let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); + match one { + Some((index, pat)) => { + for (_, other_pat) in iter { + if !matches!(other_pat.kind, PatKind::Wild) { + return None; + } + } + Some(Fields::Index(index, pat.span)) + }, + None => Some(Fields::Unused), } } -fn get_the_one>(pat: impl Iterator)>) -> Option { - let mut iter = pat.filter(|&(_, pat)| !matches!(pat.kind, PatKind::Wild)).map(|t| t.0); - let the_one = iter.next(); // TODO: this also eliminates blank patterns, e.g. Struct { .. } - as silly as it is - if iter.next().is_none() { - the_one.map(|id| id.into()).or(Some(Fields::Unused)) - } else { - None +fn get_one_id(pats: &[PatField<'a>]) -> Option { + let mut iter = pats.iter(); + let one = iter.by_ref().find(|field| !matches!(field.pat.kind, PatKind::Wild)); + match one { + Some(field) => { + for other in iter { + if !matches!(other.pat.kind, PatKind::Wild) { + return None; + } + } + Some(Fields::Id(field.ident, field.pat.span)) + }, + None => Some(Fields::Unused), } } fn single_struct(pat: &PatKind<'_>) -> Option { match pat { - PatKind::Struct(_, pats, _) => get_the_one(pats.iter().map(|field| (field.ident, field.pat))), + PatKind::Struct(_, pats, _) => get_one_id(pats), PatKind::TupleStruct(_, pats, leap) => single_tuple_inner(pats, leap), _ => None, } } fn single_tuple_inner(pats: &&[Pat<'_>], leap: &Option) -> Option { - match get_the_one((*pats).iter().enumerate()) { - field @ Some(Fields::Index(index)) => { - // Skip (.., x) - the meaning of let (.., x) = t and t.n are different - if (*leap).map_or(true, |leap_index| leap_index > index) { - field - } else { - None + get_one_index(*pats).and_then(|field| { + if let Fields::Index(index, ..) = field { + if let Some(leap_index) = *leap { + if leap_index <= index { + return None; + } } - }, - field @ Some(Fields::Unused) => field, - _ => None, - } + } + Some(field) + }) } fn single_tuple(pat: &PatKind<'_>) -> Option { @@ -103,7 +123,7 @@ fn single_tuple(pat: &PatKind<'_>) -> Option { fn single_slice(pat: &PatKind<'_>) -> Option { if let PatKind::Slice(before, dots, after) = pat { if dots.is_none() || after.len() == 0 { - return get_the_one(before.iter().enumerate()); + return get_one_index(before); } } None @@ -114,11 +134,13 @@ fn walk_until_single_field_leaf<'hir>( get_leaf: &impl Fn(&PatKind<'hir>) -> Option, ) -> Option { let mut fields = patterns + // add span of this too .map(|pat| match &pat.kind { PatKind::Or(pats) => walk_until_single_field_leaf(pats.iter(), get_leaf), PatKind::Wild => Some(Fields::Unused), p => get_leaf(p), }) + // stop filtering .filter(|field| *field != Some(Fields::Unused)); if let Some(the_one) = fields.next() { if fields.all(|other| other == the_one) { @@ -127,6 +149,7 @@ fn walk_until_single_field_leaf<'hir>( None } } else { + // emit warning saying useless match Some(Fields::Unused) } } From 37b62877dc729c512897ab8a76e17ad384529010 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 15 Dec 2021 00:38:42 -0500 Subject: [PATCH 06/47] Refactor for DRY and to get rid of recursion --- clippy_lints/src/single_field_pattern.rs | 108 +++++++++++++++-------- 1 file changed, 73 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index dfe59b2f63a3..8c928d783074 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -30,7 +30,7 @@ declare_lint_pass!(SingleFieldPattern => [SINGLE_FIELD_PATTERN]); #[derive(Debug, Clone, Copy)] enum Fields { - Id(Ident, Span), + Id(Ident, Span), // these are the pattern span - for possible conversion to string Index(usize, Span), Unused, } @@ -59,8 +59,23 @@ impl Fields { } } -fn get_one_index(pats: &[Pat<'a>]) -> Option { - let mut iter = pats.iter().enumerate(); +trait IntoFields { + fn into_fields(self, span: Span) -> Fields; +} + +impl IntoFields for Ident { + fn into_fields(self, span: Span) -> Fields { + Fields::Id(self, span) + } +} + +impl IntoFields for usize { + fn into_fields(self, span: Span) -> Fields { + Fields::Index(self, span) + } +} + +fn get_the_one<'a, ID: IntoFields>(mut iter: impl Iterator)>) -> Option { let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); match one { Some((index, pat)) => { @@ -69,23 +84,7 @@ fn get_one_index(pats: &[Pat<'a>]) -> Option { return None; } } - Some(Fields::Index(index, pat.span)) - }, - None => Some(Fields::Unused), - } -} - -fn get_one_id(pats: &[PatField<'a>]) -> Option { - let mut iter = pats.iter(); - let one = iter.by_ref().find(|field| !matches!(field.pat.kind, PatKind::Wild)); - match one { - Some(field) => { - for other in iter { - if !matches!(other.pat.kind, PatKind::Wild) { - return None; - } - } - Some(Fields::Id(field.ident, field.pat.span)) + Some(index.into_fields(pat.span)) }, None => Some(Fields::Unused), } @@ -93,14 +92,14 @@ fn get_one_id(pats: &[PatField<'a>]) -> Option { fn single_struct(pat: &PatKind<'_>) -> Option { match pat { - PatKind::Struct(_, pats, _) => get_one_id(pats), + PatKind::Struct(_, pats, _) => get_the_one(pats.iter().map(|field| (field.ident, field.pat))), PatKind::TupleStruct(_, pats, leap) => single_tuple_inner(pats, leap), _ => None, } } fn single_tuple_inner(pats: &&[Pat<'_>], leap: &Option) -> Option { - get_one_index(*pats).and_then(|field| { + get_the_one(pats.iter().enumerate()).and_then(|field| { if let Fields::Index(index, ..) = field { if let Some(leap_index) = *leap { if leap_index <= index { @@ -123,34 +122,73 @@ fn single_tuple(pat: &PatKind<'_>) -> Option { fn single_slice(pat: &PatKind<'_>) -> Option { if let PatKind::Slice(before, dots, after) = pat { if dots.is_none() || after.len() == 0 { - return get_one_index(before); + return get_the_one(before.iter().enumerate()); } } None } +/// This handles recursive patterns and flattens them out lazily +/// That basically just means handling stuff like 1 | (2 | 9) | 3..5 +struct FlatPatterns<'hir, I> +where + I: Iterator>, +{ + patterns: I, + stack: Vec<&'hir Pat<'hir>>, +} + +impl>> FlatPatterns<'hir, I> { + fn new(patterns: I) -> Self { + Self { + patterns, + stack: Vec::new(), + } + } +} + +impl>> Iterator for FlatPatterns<'hir, I> { + type Item = &'hir Pat<'hir>; + + fn next(&mut self) -> Option { + if self.stack.len() == 0 { + if let Some(pat) = self.patterns.next() { + self.stack.push(pat); + } else { + return None; + } + } + while let Some(pat) = self.stack.pop() { + match pat.kind { + PatKind::Or(pats) => self.stack.extend(pats), + _ => return Some(pat), + } + } + None + } +} + fn walk_until_single_field_leaf<'hir>( patterns: impl Iterator>, get_leaf: &impl Fn(&PatKind<'hir>) -> Option, ) -> Option { - let mut fields = patterns - // add span of this too - .map(|pat| match &pat.kind { - PatKind::Or(pats) => walk_until_single_field_leaf(pats.iter(), get_leaf), - PatKind::Wild => Some(Fields::Unused), - p => get_leaf(p), - }) - // stop filtering - .filter(|field| *field != Some(Fields::Unused)); + let mut fields = FlatPatterns::new(patterns).map(|p| { + if matches!(p.kind, PatKind::Wild) { + Some(Fields::Unused) // todo: add pat span so we can replace it + } else { + get_leaf(&p.kind) + } + }); if let Some(the_one) = fields.next() { - if fields.all(|other| other == the_one) { + if fields.all(|other| other == the_one || matches!(other, Some(Fields::Unused))) { the_one } else { None } } else { - // emit warning saying useless match - Some(Fields::Unused) + // This should only happen if the first one was None + // In which case we have one with 2+ and don't have a lint + None } } From fcddebfd20e2fac35263089387148bd426f5c03d Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 15 Dec 2021 08:55:34 -0500 Subject: [PATCH 07/47] renaming --- clippy_lints/src/single_field_pattern.rs | 52 ++++++++++++------------ 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index 8c928d783074..15b02a598629 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -75,7 +75,7 @@ impl IntoFields for usize { } } -fn get_the_one<'a, ID: IntoFields>(mut iter: impl Iterator)>) -> Option { +fn get_sf<'a, ID: IntoFields>(mut iter: impl Iterator)>) -> Option { let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); match one { Some((index, pat)) => { @@ -90,16 +90,16 @@ fn get_the_one<'a, ID: IntoFields>(mut iter: impl Iterator) -> Option { +fn struct_sf(pat: &PatKind<'_>) -> Option { match pat { - PatKind::Struct(_, pats, _) => get_the_one(pats.iter().map(|field| (field.ident, field.pat))), - PatKind::TupleStruct(_, pats, leap) => single_tuple_inner(pats, leap), + PatKind::Struct(_, pats, _) => get_sf(pats.iter().map(|field| (field.ident, field.pat))), + PatKind::TupleStruct(_, pats, leap) => inner_tuple_sf(pats, leap), _ => None, } } -fn single_tuple_inner(pats: &&[Pat<'_>], leap: &Option) -> Option { - get_the_one(pats.iter().enumerate()).and_then(|field| { +fn inner_tuple_sf(pats: &&[Pat<'_>], leap: &Option) -> Option { + get_sf(pats.iter().enumerate()).and_then(|field| { if let Fields::Index(index, ..) = field { if let Some(leap_index) = *leap { if leap_index <= index { @@ -111,18 +111,18 @@ fn single_tuple_inner(pats: &&[Pat<'_>], leap: &Option) -> Option }) } -fn single_tuple(pat: &PatKind<'_>) -> Option { +fn tuple_sf(pat: &PatKind<'_>) -> Option { if let PatKind::Tuple(pats, leap) = pat { - single_tuple_inner(pats, leap) + inner_tuple_sf(pats, leap) } else { None } } -fn single_slice(pat: &PatKind<'_>) -> Option { +fn slice_sf(pat: &PatKind<'_>) -> Option { if let PatKind::Slice(before, dots, after) = pat { if dots.is_none() || after.len() == 0 { - return get_the_one(before.iter().enumerate()); + return get_sf(before.iter().enumerate()); } } None @@ -168,17 +168,20 @@ impl>> Iterator for FlatPatterns<'hir, I> { } } -fn walk_until_single_field_leaf<'hir>( +fn find_sf_lint<'hir>( patterns: impl Iterator>, - get_leaf: &impl Fn(&PatKind<'hir>) -> Option, + leaf_sf: &impl Fn(&PatKind<'hir>) -> Option, ) -> Option { + // todo - return an Option> - previous for the scrutinee, latter to + // replace patterns appropriately - 2 spans to map a pattern span to a struct match span let mut fields = FlatPatterns::new(patterns).map(|p| { if matches!(p.kind, PatKind::Wild) { Some(Fields::Unused) // todo: add pat span so we can replace it } else { - get_leaf(&p.kind) + leaf_sf(&p.kind) } }); + // todo: handle initial unused case - this should be the first one with an actual field if let Some(the_one) = fields.next() { if fields.all(|other| other == the_one || matches!(other, Some(Fields::Unused))) { the_one @@ -186,25 +189,24 @@ fn walk_until_single_field_leaf<'hir>( None } } else { - // This should only happen if the first one was None - // In which case we have one with 2+ and don't have a lint + // This should only happen if patterns is empty None } } -fn find_single_pattern<'hir>(ty: &ty::TyKind<'_>, patterns: impl Iterator>) -> Option { +fn typed_sf_lint<'hir>(ty: &ty::TyKind<'_>, patterns: impl Iterator>) -> Option { match ty { ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.variants.raw.len() == 1 => { - walk_until_single_field_leaf(patterns, &single_struct) + find_sf_lint(patterns, &struct_sf) }, - ty::TyKind::Array(..) => walk_until_single_field_leaf(patterns, &single_slice), - ty::TyKind::Tuple(..) => walk_until_single_field_leaf(patterns, &single_tuple), + ty::TyKind::Array(..) => find_sf_lint(patterns, &slice_sf), + ty::TyKind::Tuple(..) => find_sf_lint(patterns, &tuple_sf), _ => None, } } -fn expr_helper<'hir>(cx: &LateContext<'_>, scrutinee: &Expr<'_>, patterns: impl Iterator>) { - find_single_pattern(cx.typeck_results().expr_ty(scrutinee).kind(), patterns) +fn expr_sf_lint<'hir>(cx: &LateContext<'_>, scrutinee: &Expr<'_>, patterns: impl Iterator>) { + typed_sf_lint(cx.typeck_results().expr_ty(scrutinee).kind(), patterns) .map(|pattern| pattern.lint(cx, scrutinee.span)); } @@ -215,12 +217,12 @@ impl LateLintPass<'_> for SingleFieldPattern { } match IfLetOrMatch::parse(cx, expr) { Some(IfLetOrMatch::Match(scrutinee, arms, MatchSource::Normal)) => { - expr_helper(cx, scrutinee, arms.iter().map(|arm| arm.pat)) + expr_sf_lint(cx, scrutinee, arms.iter().map(|arm| arm.pat)) }, - Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => expr_helper(cx, scrutinee, once(pat)), + Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => expr_sf_lint(cx, scrutinee, once(pat)), _ => { if let Some(WhileLet { let_pat, let_expr, .. }) = WhileLet::hir(expr) { - expr_helper(cx, let_expr, once(let_pat)) + expr_sf_lint(cx, let_expr, once(let_pat)) } }, }; @@ -238,7 +240,7 @@ impl LateLintPass<'_> for SingleFieldPattern { } else { return; }; - find_single_pattern(scrut_type, once(*pat)).map(|field| field.lint(cx, stmt.span)); + typed_sf_lint(scrut_type, once(*pat)).map(|field| field.lint(cx, stmt.span)); } } } From 2ff63f8c41ca604574e66d698398fb4834184f10 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 15 Dec 2021 09:00:47 -0500 Subject: [PATCH 08/47] convert tuple struct to named struct --- clippy_lints/src/single_field_pattern.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index 15b02a598629..0666a8e3c0a4 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -30,8 +30,8 @@ declare_lint_pass!(SingleFieldPattern => [SINGLE_FIELD_PATTERN]); #[derive(Debug, Clone, Copy)] enum Fields { - Id(Ident, Span), // these are the pattern span - for possible conversion to string - Index(usize, Span), + Id { id: Ident, pattern: Span }, + Index { index: usize, pattern: Span }, Unused, } use Fields::*; @@ -39,8 +39,8 @@ use Fields::*; impl PartialEq for Fields { fn eq(&self, other: &Self) -> bool { match (self, other) { - (Id(id1, ..), Id(id2, ..)) => id1 == id2, - (Index(index1, ..), Index(index2, ..)) => index1 == index2, + (Id { id: id1, .. }, Id { id: id2, .. }) => id1 == id2, + (Index { index: index1, .. }, Index { index: index2, .. }) => index1 == index2, (Unused, Unused) => true, _ => false, } @@ -64,14 +64,14 @@ trait IntoFields { } impl IntoFields for Ident { - fn into_fields(self, span: Span) -> Fields { - Fields::Id(self, span) + fn into_fields(self, pattern: Span) -> Fields { + Fields::Id { id: self, pattern } } } impl IntoFields for usize { - fn into_fields(self, span: Span) -> Fields { - Fields::Index(self, span) + fn into_fields(self, pattern: Span) -> Fields { + Fields::Index { index: self, pattern } } } @@ -100,7 +100,7 @@ fn struct_sf(pat: &PatKind<'_>) -> Option { fn inner_tuple_sf(pats: &&[Pat<'_>], leap: &Option) -> Option { get_sf(pats.iter().enumerate()).and_then(|field| { - if let Fields::Index(index, ..) = field { + if let Fields::Index { index, .. } = field { if let Some(leap_index) = *leap { if leap_index <= index { return None; From 212b617f62b70197ada20963e2f9bbefda5c3672 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 15 Dec 2021 09:02:39 -0500 Subject: [PATCH 09/47] rename to SingleField --- clippy_lints/src/single_field_pattern.rs | 42 ++++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index 0666a8e3c0a4..d3328a9b9428 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -29,15 +29,15 @@ declare_clippy_lint! { declare_lint_pass!(SingleFieldPattern => [SINGLE_FIELD_PATTERN]); #[derive(Debug, Clone, Copy)] -enum Fields { +enum SingleField { Id { id: Ident, pattern: Span }, Index { index: usize, pattern: Span }, Unused, } -use Fields::*; -impl PartialEq for Fields { +impl PartialEq for SingleField { fn eq(&self, other: &Self) -> bool { + use SingleField::*; match (self, other) { (Id { id: id1, .. }, Id { id: id2, .. }) => id1 == id2, (Index { index: index1, .. }, Index { index: index2, .. }) => index1 == index2, @@ -47,7 +47,7 @@ impl PartialEq for Fields { } } -impl Fields { +impl SingleField { // Todo - auto-fix - I'll need to add span and strings into SingleField fn lint(self, cx: &LateContext<'_>, span: impl Into) { span_lint( @@ -60,22 +60,22 @@ impl Fields { } trait IntoFields { - fn into_fields(self, span: Span) -> Fields; + fn into_fields(self, span: Span) -> SingleField; } impl IntoFields for Ident { - fn into_fields(self, pattern: Span) -> Fields { - Fields::Id { id: self, pattern } + fn into_fields(self, pattern: Span) -> SingleField { + SingleField::Id { id: self, pattern } } } impl IntoFields for usize { - fn into_fields(self, pattern: Span) -> Fields { - Fields::Index { index: self, pattern } + fn into_fields(self, pattern: Span) -> SingleField { + SingleField::Index { index: self, pattern } } } -fn get_sf<'a, ID: IntoFields>(mut iter: impl Iterator)>) -> Option { +fn get_sf<'a, ID: IntoFields>(mut iter: impl Iterator)>) -> Option { let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); match one { Some((index, pat)) => { @@ -86,11 +86,11 @@ fn get_sf<'a, ID: IntoFields>(mut iter: impl Iterator)>) } Some(index.into_fields(pat.span)) }, - None => Some(Fields::Unused), + None => Some(SingleField::Unused), } } -fn struct_sf(pat: &PatKind<'_>) -> Option { +fn struct_sf(pat: &PatKind<'_>) -> Option { match pat { PatKind::Struct(_, pats, _) => get_sf(pats.iter().map(|field| (field.ident, field.pat))), PatKind::TupleStruct(_, pats, leap) => inner_tuple_sf(pats, leap), @@ -98,9 +98,9 @@ fn struct_sf(pat: &PatKind<'_>) -> Option { } } -fn inner_tuple_sf(pats: &&[Pat<'_>], leap: &Option) -> Option { +fn inner_tuple_sf(pats: &&[Pat<'_>], leap: &Option) -> Option { get_sf(pats.iter().enumerate()).and_then(|field| { - if let Fields::Index { index, .. } = field { + if let SingleField::Index { index, .. } = field { if let Some(leap_index) = *leap { if leap_index <= index { return None; @@ -111,7 +111,7 @@ fn inner_tuple_sf(pats: &&[Pat<'_>], leap: &Option) -> Option { }) } -fn tuple_sf(pat: &PatKind<'_>) -> Option { +fn tuple_sf(pat: &PatKind<'_>) -> Option { if let PatKind::Tuple(pats, leap) = pat { inner_tuple_sf(pats, leap) } else { @@ -119,7 +119,7 @@ fn tuple_sf(pat: &PatKind<'_>) -> Option { } } -fn slice_sf(pat: &PatKind<'_>) -> Option { +fn slice_sf(pat: &PatKind<'_>) -> Option { if let PatKind::Slice(before, dots, after) = pat { if dots.is_none() || after.len() == 0 { return get_sf(before.iter().enumerate()); @@ -170,20 +170,20 @@ impl>> Iterator for FlatPatterns<'hir, I> { fn find_sf_lint<'hir>( patterns: impl Iterator>, - leaf_sf: &impl Fn(&PatKind<'hir>) -> Option, -) -> Option { + leaf_sf: &impl Fn(&PatKind<'hir>) -> Option, +) -> Option { // todo - return an Option> - previous for the scrutinee, latter to // replace patterns appropriately - 2 spans to map a pattern span to a struct match span let mut fields = FlatPatterns::new(patterns).map(|p| { if matches!(p.kind, PatKind::Wild) { - Some(Fields::Unused) // todo: add pat span so we can replace it + Some(SingleField::Unused) // todo: add pat span so we can replace it } else { leaf_sf(&p.kind) } }); // todo: handle initial unused case - this should be the first one with an actual field if let Some(the_one) = fields.next() { - if fields.all(|other| other == the_one || matches!(other, Some(Fields::Unused))) { + if fields.all(|other| other == the_one || matches!(other, Some(SingleField::Unused))) { the_one } else { None @@ -194,7 +194,7 @@ fn find_sf_lint<'hir>( } } -fn typed_sf_lint<'hir>(ty: &ty::TyKind<'_>, patterns: impl Iterator>) -> Option { +fn typed_sf_lint<'hir>(ty: &ty::TyKind<'_>, patterns: impl Iterator>) -> Option { match ty { ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.variants.raw.len() == 1 => { find_sf_lint(patterns, &struct_sf) From bf57033ebcd0b058be73544d767ddcb37a630f7d Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 15 Dec 2021 09:04:14 -0500 Subject: [PATCH 10/47] refactor: move code --- clippy_lints/src/single_field_pattern.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index d3328a9b9428..faf7ff4f041b 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -90,14 +90,6 @@ fn get_sf<'a, ID: IntoFields>(mut iter: impl Iterator)>) } } -fn struct_sf(pat: &PatKind<'_>) -> Option { - match pat { - PatKind::Struct(_, pats, _) => get_sf(pats.iter().map(|field| (field.ident, field.pat))), - PatKind::TupleStruct(_, pats, leap) => inner_tuple_sf(pats, leap), - _ => None, - } -} - fn inner_tuple_sf(pats: &&[Pat<'_>], leap: &Option) -> Option { get_sf(pats.iter().enumerate()).and_then(|field| { if let SingleField::Index { index, .. } = field { @@ -111,6 +103,14 @@ fn inner_tuple_sf(pats: &&[Pat<'_>], leap: &Option) -> Option) -> Option { + match pat { + PatKind::Struct(_, pats, _) => get_sf(pats.iter().map(|field| (field.ident, field.pat))), + PatKind::TupleStruct(_, pats, leap) => inner_tuple_sf(pats, leap), + _ => None, + } +} + fn tuple_sf(pat: &PatKind<'_>) -> Option { if let PatKind::Tuple(pats, leap) = pat { inner_tuple_sf(pats, leap) From 9d62c7057c737d86a360888986ea7603d8c1f601 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 15 Dec 2021 09:05:36 -0500 Subject: [PATCH 11/47] refactor: rename --- clippy_lints/src/single_field_pattern.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index faf7ff4f041b..e84c67670176 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -59,23 +59,23 @@ impl SingleField { } } -trait IntoFields { - fn into_fields(self, span: Span) -> SingleField; +trait IntoSingleField { + fn into_sf(self, span: Span) -> SingleField; } -impl IntoFields for Ident { - fn into_fields(self, pattern: Span) -> SingleField { +impl IntoSingleField for Ident { + fn into_sf(self, pattern: Span) -> SingleField { SingleField::Id { id: self, pattern } } } -impl IntoFields for usize { - fn into_fields(self, pattern: Span) -> SingleField { +impl IntoSingleField for usize { + fn into_sf(self, pattern: Span) -> SingleField { SingleField::Index { index: self, pattern } } } -fn get_sf<'a, ID: IntoFields>(mut iter: impl Iterator)>) -> Option { +fn get_sf<'a, ID: IntoSingleField>(mut iter: impl Iterator)>) -> Option { let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); match one { Some((index, pat)) => { @@ -84,7 +84,7 @@ fn get_sf<'a, ID: IntoFields>(mut iter: impl Iterator)>) return None; } } - Some(index.into_fields(pat.span)) + Some(index.into_sf(pat.span)) }, None => Some(SingleField::Unused), } From 73ed511818f4163bd3f625b11c29c72d10d5efaf Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 15 Dec 2021 18:51:25 -0500 Subject: [PATCH 12/47] get span mapping --- clippy_lints/src/single_field_pattern.rs | 63 +++++++++++++++++------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_pattern.rs index e84c67670176..866ba07e2d15 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_pattern.rs @@ -79,12 +79,11 @@ fn get_sf<'a, ID: IntoSingleField>(mut iter: impl Iterator { - for (_, other_pat) in iter { - if !matches!(other_pat.kind, PatKind::Wild) { - return None; - } + if iter.all(|(_, other)| matches!(other.kind, PatKind::Wild)) { + Some(index.into_sf(pat.span)) + } else { + None } - Some(index.into_sf(pat.span)) }, None => Some(SingleField::Unused), } @@ -172,25 +171,53 @@ fn find_sf_lint<'hir>( patterns: impl Iterator>, leaf_sf: &impl Fn(&PatKind<'hir>) -> Option, ) -> Option { - // todo - return an Option> - previous for the scrutinee, latter to - // replace patterns appropriately - 2 spans to map a pattern span to a struct match span - let mut fields = FlatPatterns::new(patterns).map(|p| { - if matches!(p.kind, PatKind::Wild) { - Some(SingleField::Unused) // todo: add pat span so we can replace it + let fields = FlatPatterns::new(patterns).map(|p| { + ( + p.span, + if matches!(p.kind, PatKind::Wild) { + Some(SingleField::Unused) + } else { + leaf_sf(&p.kind) + }, + ) + }); + // if we can somehow replace this operation and this vec with an iterator, that'd be nice + // this is slightly difficult because it's a two-part operation + // prior = iter.as_ref().find_partition(...first id...) + // latter = iter. + let mut spans = Vec::<(Span, Option)>::new(); + let mut the_one: Option = None; + for (target, sf) in fields { + if let Some(sf) = sf { + match sf { + SingleField::Unused => { + // this doesn't work if all fields are unused + // Maybe out of scope, but not handled by another lint? + spans.push((target, None)); + }, + SingleField::Id { pattern, .. } | SingleField::Index { pattern, .. } => { + spans.push((target, Some(pattern))); + if let Some(one) = the_one { + if sf != one { + return None; + } + } else { + the_one = Some(sf); + } + }, + } } else { - leaf_sf(&p.kind) + return None; } - }); - // todo: handle initial unused case - this should be the first one with an actual field - if let Some(the_one) = fields.next() { - if fields.all(|other| other == the_one || matches!(other, Some(SingleField::Unused))) { - the_one + } + if the_one.is_none() { + if spans.len() > 0 { + Some(SingleField::Unused) } else { None } } else { - // This should only happen if patterns is empty - None + the_one } } From 4107c44e7192d764e27915a92841986fd81a3d0d Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 18 Dec 2021 11:15:57 -0500 Subject: [PATCH 13/47] moved file, added suggestions --- CHANGELOG.md | 2 +- clippy_lints/src/lib.register_all.rs | 2 +- clippy_lints/src/lib.register_lints.rs | 2 +- clippy_lints/src/lib.register_style.rs | 2 +- clippy_lints/src/lib.rs | 4 +- ...ld_pattern.rs => single_field_patterns.rs} | 156 ++++++++++++------ tests/ui/single_field_pattern.rs | 2 +- 7 files changed, 111 insertions(+), 59 deletions(-) rename clippy_lints/src/{single_field_pattern.rs => single_field_patterns.rs} (60%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6c2ab9dc4f7..2cbdff9d6c9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3140,7 +3140,7 @@ Released 2018-09-13 [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern [`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop -[`single_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_field_pattern +[`single_field_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_field_patterns [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs index cfb303c021d6..9bde42923b8e 100644 --- a/clippy_lints/src/lib.register_all.rs +++ b/clippy_lints/src/lib.register_all.rs @@ -252,7 +252,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), LintId::of(serde_api::SERDE_API_MISUSE), LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), - LintId::of(single_field_pattern::SINGLE_FIELD_PATTERN), + LintId::of(single_field_patterns::SINGLE_FIELD_PATTERNS), LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs index ea236531da1f..1b2e57823276 100644 --- a/clippy_lints/src/lib.register_lints.rs +++ b/clippy_lints/src/lib.register_lints.rs @@ -433,7 +433,7 @@ store.register_lints(&[ shadow::SHADOW_SAME, shadow::SHADOW_UNRELATED, single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, - single_field_pattern::SINGLE_FIELD_PATTERN, + single_field_patterns::SINGLE_FIELD_PATTERNS, size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT, slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, stable_sort_primitive::STABLE_SORT_PRIMITIVE, diff --git a/clippy_lints/src/lib.register_style.rs b/clippy_lints/src/lib.register_style.rs index 90f8c05a5832..022bccbb9519 100644 --- a/clippy_lints/src/lib.register_style.rs +++ b/clippy_lints/src/lib.register_style.rs @@ -99,7 +99,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(returns::NEEDLESS_RETURN), LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), - LintId::of(single_field_pattern::SINGLE_FIELD_PATTERN), + LintId::of(single_field_patterns::SINGLE_FIELD_PATTERNS), LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), LintId::of(try_err::TRY_ERR), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c57c6a25176e..6274eb91c95f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -349,7 +349,7 @@ mod semicolon_if_nothing_returned; mod serde_api; mod shadow; mod single_component_path_imports; -mod single_field_pattern; +mod single_field_patterns; mod size_of_in_element_count; mod slow_vector_initialization; mod stable_sort_primitive; @@ -854,7 +854,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray)); store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes)); store.register_late_pass(|| Box::new(needless_late_init::NeedlessLateInit)); - store.register_late_pass(|| Box::new(single_field_pattern::SingleFieldPattern)); + store.register_late_pass(|| Box::new(single_field_patterns::SingleFieldPatterns)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/single_field_pattern.rs b/clippy_lints/src/single_field_patterns.rs similarity index 60% rename from clippy_lints/src/single_field_pattern.rs rename to clippy_lints/src/single_field_patterns.rs index 866ba07e2d15..bb68daec9b8d 100644 --- a/clippy_lints/src/single_field_pattern.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -1,11 +1,17 @@ #![allow(rustc::usage_of_ty_tykind)] -use clippy_utils::{diagnostics::span_lint, higher::IfLetOrMatch, higher::WhileLet}; +use clippy_utils::{ + diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}, + higher::IfLetOrMatch, + higher::WhileLet, + source::snippet_opt, +}; +use rustc_errors::Applicability; use rustc_hir::*; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{symbol::Ident, MultiSpan, Span}; +use rustc_span::{symbol::Ident, Span}; use std::iter::once; declare_clippy_lint! { @@ -22,17 +28,17 @@ declare_clippy_lint! { /// // example code which does not raise clippy warning /// ``` #[clippy::version = "1.59.0"] - pub SINGLE_FIELD_PATTERN, + pub SINGLE_FIELD_PATTERNS, style, "default lint description" } -declare_lint_pass!(SingleFieldPattern => [SINGLE_FIELD_PATTERN]); +declare_lint_pass!(SingleFieldPatterns => [SINGLE_FIELD_PATTERNS]); #[derive(Debug, Clone, Copy)] enum SingleField { Id { id: Ident, pattern: Span }, Index { index: usize, pattern: Span }, - Unused, + Unused, // The name "SingleField" is a lie but idk what's better. "AtMostOneField"? } impl PartialEq for SingleField { @@ -47,18 +53,6 @@ impl PartialEq for SingleField { } } -impl SingleField { - // Todo - auto-fix - I'll need to add span and strings into SingleField - fn lint(self, cx: &LateContext<'_>, span: impl Into) { - span_lint( - cx, - SINGLE_FIELD_PATTERN, - span, - "pattern matching just to get a single field", - ); - } -} - trait IntoSingleField { fn into_sf(self, span: Span) -> SingleField; } @@ -167,10 +161,11 @@ impl>> Iterator for FlatPatterns<'hir, I> { } } -fn find_sf_lint<'hir>( +fn find_sf_lint<'hir, T: LintContext>( + cx: &T, patterns: impl Iterator>, leaf_sf: &impl Fn(&PatKind<'hir>) -> Option, -) -> Option { +) -> Option<(SingleField, Vec<(Span, String)>)> { let fields = FlatPatterns::new(patterns).map(|p| { ( p.span, @@ -185,7 +180,7 @@ fn find_sf_lint<'hir>( // this is slightly difficult because it's a two-part operation // prior = iter.as_ref().find_partition(...first id...) // latter = iter. - let mut spans = Vec::<(Span, Option)>::new(); + let mut spans = Vec::<(Span, String)>::new(); let mut the_one: Option = None; for (target, sf) in fields { if let Some(sf) = sf { @@ -193,10 +188,14 @@ fn find_sf_lint<'hir>( SingleField::Unused => { // this doesn't work if all fields are unused // Maybe out of scope, but not handled by another lint? - spans.push((target, None)); + spans.push((target, String::from("_"))); }, SingleField::Id { pattern, .. } | SingleField::Index { pattern, .. } => { - spans.push((target, Some(pattern))); + if let Some(str) = snippet_opt(cx, pattern) { + spans.push((target, str)); + } else { + return None; + } if let Some(one) = the_one { if sf != one { return None; @@ -210,46 +209,98 @@ fn find_sf_lint<'hir>( return None; } } - if the_one.is_none() { - if spans.len() > 0 { - Some(SingleField::Unused) - } else { - None - } + if spans.len() > 0 { + Some((the_one.unwrap_or(SingleField::Unused), spans)) } else { - the_one + None } } -fn typed_sf_lint<'hir>(ty: &ty::TyKind<'_>, patterns: impl Iterator>) -> Option { +fn apply_lint(cx: &T, span: Span, sugg: impl IntoIterator) { + span_lint_and_then( + cx, + SINGLE_FIELD_PATTERNS, + span, + "use at most 1 of field in this pattern - consider indexing it", + |diag| { + multispan_sugg_with_applicability(diag, "try this", Applicability::MachineApplicable, sugg); + }, + ); +} + +fn typed_sf_lint<'hir, T: LintContext>( + cx: &T, + overall_span: Span, + scrutinee_span: Span, + ty: &ty::TyKind<'_>, + patterns: impl Iterator>, +) { + let scrutinee_name = if let Some(name) = snippet_opt(cx, scrutinee_span) { + name + } else { + return; + }; match ty { ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.variants.raw.len() == 1 => { - find_sf_lint(patterns, &struct_sf) + if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &struct_sf) { + if let SingleField::Id { id, .. } = field { + spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, id.as_str()))); + apply_lint(cx, overall_span, spans); + } else if let SingleField::Index { index, .. } = field { + spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, index))); + apply_lint(cx, overall_span, spans); + } + } }, - ty::TyKind::Array(..) => find_sf_lint(patterns, &slice_sf), - ty::TyKind::Tuple(..) => find_sf_lint(patterns, &tuple_sf), - _ => None, - } + ty::TyKind::Array(..) => { + if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &slice_sf) { + if let SingleField::Index { index, .. } = field { + spans.push((scrutinee_span, format!("{}[{}]", scrutinee_name, index))); + apply_lint(cx, overall_span, spans); + } + } + }, + ty::TyKind::Tuple(..) => { + if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &tuple_sf) { + if let SingleField::Index { index, .. } = field { + spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, index))); + apply_lint(cx, overall_span, spans); + } + } + }, + _ => (), + }; } -fn expr_sf_lint<'hir>(cx: &LateContext<'_>, scrutinee: &Expr<'_>, patterns: impl Iterator>) { - typed_sf_lint(cx.typeck_results().expr_ty(scrutinee).kind(), patterns) - .map(|pattern| pattern.lint(cx, scrutinee.span)); +fn expr_sf_lint<'hir>( + cx: &LateContext<'_>, + overall_span: Span, + scrutinee: &Expr<'_>, + patterns: impl Iterator>, +) { + typed_sf_lint( + cx, + overall_span, + scrutinee.span, + cx.typeck_results().expr_ty(scrutinee).kind(), + patterns, + ); } -impl LateLintPass<'_> for SingleFieldPattern { +impl LateLintPass<'_> for SingleFieldPatterns { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if expr.span.from_expansion() { return; } match IfLetOrMatch::parse(cx, expr) { Some(IfLetOrMatch::Match(scrutinee, arms, MatchSource::Normal)) => { - expr_sf_lint(cx, scrutinee, arms.iter().map(|arm| arm.pat)) + expr_sf_lint(cx, expr.span, scrutinee, arms.iter().map(|arm| arm.pat)); }, - Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => expr_sf_lint(cx, scrutinee, once(pat)), + Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => expr_sf_lint(cx, expr.span, scrutinee, once(pat)), _ => { + // todo for maybe, other missing patterns if let Some(WhileLet { let_pat, let_expr, .. }) = WhileLet::hir(expr) { - expr_sf_lint(cx, let_expr, once(let_pat)) + expr_sf_lint(cx, expr.span, let_expr, once(let_pat)); } }, }; @@ -259,15 +310,16 @@ impl LateLintPass<'_> for SingleFieldPattern { if stmt.span.from_expansion() { return; } - if let StmtKind::Local(Local { pat, ty, init, .. }) = stmt.kind { - let scrut_type = if let Some(t) = *ty { - cx.typeck_results().node_type(t.hir_id).kind() - } else if let Some(e) = init { - cx.typeck_results().expr_ty(e).kind() - } else { - return; - }; - typed_sf_lint(scrut_type, once(*pat)).map(|field| field.lint(cx, stmt.span)); + if let StmtKind::Local(Local { pat, init, .. }) = stmt.kind { + if let Some(scrutinee) = init { + typed_sf_lint( + cx, + stmt.span, + scrutinee.span, + cx.typeck_results().expr_ty(scrutinee).kind(), + once(*pat), + ); + } } } } diff --git a/tests/ui/single_field_pattern.rs b/tests/ui/single_field_pattern.rs index b95aa41e5973..cae6b8af7bfc 100644 --- a/tests/ui/single_field_pattern.rs +++ b/tests/ui/single_field_pattern.rs @@ -1,4 +1,4 @@ -#![warn(clippy::single_field_pattern)] +#![warn(clippy::single_field_patterns)] struct Struct { field1: Option, field2: Option, From 868a41bf2ad48c955fff74e23bcd443e9cb61ad4 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 18 Dec 2021 11:29:24 -0500 Subject: [PATCH 14/47] support unused patterns and bless --- clippy_lints/src/single_field_patterns.rs | 58 +++-- tests/ui/single_field_pattern.stderr | 258 ++++++++++++++++++++++ 2 files changed, 300 insertions(+), 16 deletions(-) create mode 100644 tests/ui/single_field_pattern.stderr diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index bb68daec9b8d..b048558bb26a 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -1,7 +1,7 @@ #![allow(rustc::usage_of_ty_tykind)] use clippy_utils::{ - diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}, + diagnostics::{multispan_sugg_with_applicability, span_lint, span_lint_and_then}, higher::IfLetOrMatch, higher::WhileLet, source::snippet_opt, @@ -216,18 +216,27 @@ fn find_sf_lint<'hir, T: LintContext>( } } -fn apply_lint(cx: &T, span: Span, sugg: impl IntoIterator) { +fn apply_lint_sf(cx: &T, span: Span, sugg: impl IntoIterator) { span_lint_and_then( cx, SINGLE_FIELD_PATTERNS, span, - "use at most 1 of field in this pattern - consider indexing it", + "this single-variant pattern only matches one field", |diag| { multispan_sugg_with_applicability(diag, "try this", Applicability::MachineApplicable, sugg); }, ); } +fn apply_lint_zero_fields(cx: &T, span: Span) { + span_lint( + cx, + SINGLE_FIELD_PATTERNS, + span, + "this single-variant pattern matches no fields", + ); +} + fn typed_sf_lint<'hir, T: LintContext>( cx: &T, overall_span: Span, @@ -243,28 +252,45 @@ fn typed_sf_lint<'hir, T: LintContext>( match ty { ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.variants.raw.len() == 1 => { if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &struct_sf) { - if let SingleField::Id { id, .. } = field { - spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, id.as_str()))); - apply_lint(cx, overall_span, spans); - } else if let SingleField::Index { index, .. } = field { - spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, index))); - apply_lint(cx, overall_span, spans); - } + spans.push(( + scrutinee_span, + match field { + SingleField::Id { id, .. } => format!("{}.{}", scrutinee_name, id.as_str()), + SingleField::Index { index, .. } => format!("{}.{}", scrutinee_name, index), + SingleField::Unused => { + apply_lint_zero_fields(cx, overall_span); + return; + }, + }, + )); + apply_lint_sf(cx, overall_span, spans); } }, ty::TyKind::Array(..) => { if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &slice_sf) { - if let SingleField::Index { index, .. } = field { - spans.push((scrutinee_span, format!("{}[{}]", scrutinee_name, index))); - apply_lint(cx, overall_span, spans); + match field { + SingleField::Index { index, .. } => { + spans.push((scrutinee_span, format!("{}[{}]", scrutinee_name, index))); + apply_lint_sf(cx, overall_span, spans); + }, + SingleField::Unused => { + apply_lint_zero_fields(cx, overall_span); + }, + _ => { /* shouldn't happen */ }, } } }, ty::TyKind::Tuple(..) => { if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &tuple_sf) { - if let SingleField::Index { index, .. } = field { - spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, index))); - apply_lint(cx, overall_span, spans); + match field { + SingleField::Index { index, .. } => { + spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, index))); + apply_lint_sf(cx, overall_span, spans); + }, + SingleField::Unused => { + apply_lint_zero_fields(cx, overall_span); + }, + _ => { /* shouldn't happen */ }, } } }, diff --git a/tests/ui/single_field_pattern.stderr b/tests/ui/single_field_pattern.stderr new file mode 100644 index 000000000000..b8489e0aff3f --- /dev/null +++ b/tests/ui/single_field_pattern.stderr @@ -0,0 +1,258 @@ +error: this single-variant pattern matches no fields + --> $DIR/single_field_pattern.rs:8:5 + | +LL | let Struct { .. } = struct1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::single-field-patterns` implied by `-D warnings` + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:9:5 + | +LL | let Struct { field1, .. } = struct1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | let field1 = struct1.field1; + | ~~~~~~ ~~~~~~~~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:10:5 + | +LL | let Struct { field1, field2: _ } = struct1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | let field1 = struct1.field1; + | ~~~~~~ ~~~~~~~~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:11:5 + | +LL | / match struct1 { +LL | | Struct { field1: Some(n), .. } if n >= 50 => {}, +LL | | Struct { field1: None, .. } => {}, +LL | | _ => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match struct1.field1 { +LL ~ Some(n) if n >= 50 => {}, +LL ~ None => {}, +LL ~ _ => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:16:5 + | +LL | / match struct1 { +LL | | Struct { field1: Some(n), .. } if n >= 50 => {}, +LL | | Struct { .. } => {}, +LL | | _ => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match struct1.field1 { +LL ~ Some(n) if n >= 50 => {}, +LL ~ _ => {}, +LL ~ _ => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:21:5 + | +LL | / match struct1 { +LL | | Struct { field1: Some(1), .. } => {}, +LL | | Struct { field1: Some(2), .. } => {}, +LL | | Struct { field1: None, .. } => {}, +LL | | _ => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match struct1.field1 { +LL ~ Some(1) => {}, +LL ~ Some(2) => {}, +LL ~ None => {}, +LL ~ _ => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:27:5 + | +LL | / match struct1 { +LL | | Struct { +LL | | field1: Some(_) | None, .. +LL | | } => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match struct1.field1 { +LL ~ Some(_) | None => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:32:5 + | +LL | while let Struct { field1: Some(5), .. } = struct1 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | while let Some(5) = struct1.field1 {} + | ~~~~~~~ ~~~~~~~~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:38:5 + | +LL | if let Tuple(Some(x), _) = tuple {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | if let Some(x) = tuple.0 {} + | ~~~~~~~ ~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:39:5 + | +LL | if let Tuple(_, Some(y)) = tuple {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | if let Some(y) = tuple.1 {} + | ~~~~~~~ ~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:40:5 + | +LL | / match tuple { +LL | | Tuple(Some(1), ..) => {}, +LL | | Tuple(Some(2), ..) => {}, +LL | | Tuple(a, ..) => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match tuple.0 { +LL ~ Some(1) => {}, +LL ~ Some(2) => {}, +LL ~ a => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:45:5 + | +LL | / match tuple { +LL | | Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, +LL | | Tuple(a, ..) => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match tuple.0 { +LL ~ Some(1) | Some(42) | Some(6082) => {}, +LL ~ a => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:52:5 + | +LL | if let (Some(z), _) = tuple {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | if let Some(z) = tuple.0 {} + | ~~~~~~~ ~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:53:5 + | +LL | if let (_, Some(n)) = tuple {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | if let Some(n) = tuple.1 {} + | ~~~~~~~ ~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:54:5 + | +LL | / match tuple { +LL | | (Some(1), ..) => {}, +LL | | (Some(2), ..) => {}, +LL | | (a, ..) => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match tuple.0 { +LL ~ Some(1) => {}, +LL ~ Some(2) => {}, +LL ~ a => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:59:5 + | +LL | / match tuple { +LL | | (Some(1) | Some(42) | Some(6082), ..) => {}, +LL | | (a, ..) => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match tuple.0 { +LL ~ Some(1) | Some(42) | Some(6082) => {}, +LL ~ a => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:66:5 + | +LL | / match array { +LL | | [1 | 2, ..] => {}, +LL | | [x @ 3, ..] => {}, +LL | | [r @ 20..=65, ..] => {}, +LL | | [e, ..] => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ match array[0] { +LL ~ 1 | 2 => {}, +LL ~ x @ 3 => {}, +LL ~ r @ 20..=65 => {}, +LL ~ e => {}, + | + +error: this single-variant pattern only matches one field + --> $DIR/single_field_pattern.rs:72:5 + | +LL | if let [5, ..] = array {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | if let 5 = array[0] {} + | ~ ~~~~~~~~ + +error: aborting due to 18 previous errors + From c3822001b9485bf0ae5c2d2ec516a78a10071fdc Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 18 Dec 2021 11:38:25 -0500 Subject: [PATCH 15/47] documentation --- clippy_lints/src/single_field_patterns.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index b048558bb26a..9adcc96bc2bf 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -16,16 +16,27 @@ use std::iter::once; declare_clippy_lint! { /// ### What it does + /// Checks for patterns that only use a single field when they could directly access the field + /// (note: it intentionally doesn't match [.., x] because that can be less cumbersome than a[6028]) /// /// ### Why is this bad? + /// It requires more and/or redundant information than directly accessing the field. /// /// ### Example /// ```rust - /// // example code where clippy issues a warning + /// match struct1 { + /// Struct { field1: Some(n), .. } if n >= 50 => {}, + /// Struct { field1: None, .. } => {}, + /// _ => {}, + /// } /// ``` /// Use instead: /// ```rust - /// // example code which does not raise clippy warning + /// match struct1.field1 { + /// Some(n) if n >= 50 => {}, + /// None => {}, + /// _ => {}, + /// } /// ``` #[clippy::version = "1.59.0"] pub SINGLE_FIELD_PATTERNS, From 64f356a94d9962d7a4a4972c33d2b7e944765a46 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 18 Dec 2021 11:41:28 -0500 Subject: [PATCH 16/47] docs --- clippy_lints/src/single_field_patterns.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 9adcc96bc2bf..e59207c5bc08 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -17,10 +17,9 @@ use std::iter::once; declare_clippy_lint! { /// ### What it does /// Checks for patterns that only use a single field when they could directly access the field - /// (note: it intentionally doesn't match [.., x] because that can be less cumbersome than a[6028]) /// /// ### Why is this bad? - /// It requires more and/or redundant information than directly accessing the field. + /// It requires more information than directly accessing the field. /// /// ### Example /// ```rust From 7ce79fd4e0f1b651a83ea7d9f4ed3486fc42f921 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 18 Dec 2021 11:44:46 -0500 Subject: [PATCH 17/47] docs --- clippy_lints/src/single_field_patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index e59207c5bc08..c4edca15c401 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -40,7 +40,7 @@ declare_clippy_lint! { #[clippy::version = "1.59.0"] pub SINGLE_FIELD_PATTERNS, style, - "default lint description" + "single-field patterns" } declare_lint_pass!(SingleFieldPatterns => [SINGLE_FIELD_PATTERNS]); From ea671fe0f111348474b78fef45d01a5b15bf6bb7 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 18 Dec 2021 11:52:49 -0500 Subject: [PATCH 18/47] docs --- clippy_lints/src/single_field_patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index c4edca15c401..6967d4a1ae8c 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -16,7 +16,7 @@ use std::iter::once; declare_clippy_lint! { /// ### What it does - /// Checks for patterns that only use a single field when they could directly access the field + /// Checks for patterns that only use a single field when they could directly access the field. /// /// ### Why is this bad? /// It requires more information than directly accessing the field. From 30c76c422b05e3a01ea33adbdbbfe3053dacd3d0 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 18 Dec 2021 15:52:49 -0500 Subject: [PATCH 19/47] stop handling empty patterns --- clippy_lints/src/single_field_patterns.rs | 51 ++++------------------- tests/ui/single_field_pattern.rs | 2 +- tests/ui/single_field_pattern.stderr | 45 +++++++++----------- 3 files changed, 28 insertions(+), 70 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 6967d4a1ae8c..73eb0445a5c3 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -196,8 +196,6 @@ fn find_sf_lint<'hir, T: LintContext>( if let Some(sf) = sf { match sf { SingleField::Unused => { - // this doesn't work if all fields are unused - // Maybe out of scope, but not handled by another lint? spans.push((target, String::from("_"))); }, SingleField::Id { pattern, .. } | SingleField::Index { pattern, .. } => { @@ -219,11 +217,7 @@ fn find_sf_lint<'hir, T: LintContext>( return None; } } - if spans.len() > 0 { - Some((the_one.unwrap_or(SingleField::Unused), spans)) - } else { - None - } + the_one.map(|one| (one, spans)) } fn apply_lint_sf(cx: &T, span: Span, sugg: impl IntoIterator) { @@ -238,15 +232,6 @@ fn apply_lint_sf(cx: &T, span: Span, sugg: impl IntoIterator(cx: &T, span: Span) { - span_lint( - cx, - SINGLE_FIELD_PATTERNS, - span, - "this single-variant pattern matches no fields", - ); -} - fn typed_sf_lint<'hir, T: LintContext>( cx: &T, overall_span: Span, @@ -267,41 +252,22 @@ fn typed_sf_lint<'hir, T: LintContext>( match field { SingleField::Id { id, .. } => format!("{}.{}", scrutinee_name, id.as_str()), SingleField::Index { index, .. } => format!("{}.{}", scrutinee_name, index), - SingleField::Unused => { - apply_lint_zero_fields(cx, overall_span); - return; - }, + _ => return, }, )); apply_lint_sf(cx, overall_span, spans); } }, ty::TyKind::Array(..) => { - if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &slice_sf) { - match field { - SingleField::Index { index, .. } => { - spans.push((scrutinee_span, format!("{}[{}]", scrutinee_name, index))); - apply_lint_sf(cx, overall_span, spans); - }, - SingleField::Unused => { - apply_lint_zero_fields(cx, overall_span); - }, - _ => { /* shouldn't happen */ }, - } + if let Some((SingleField::Index { index, .. }, mut spans)) = find_sf_lint(cx, patterns, &slice_sf) { + spans.push((scrutinee_span, format!("{}[{}]", scrutinee_name, index))); + apply_lint_sf(cx, overall_span, spans); } }, ty::TyKind::Tuple(..) => { - if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &tuple_sf) { - match field { - SingleField::Index { index, .. } => { - spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, index))); - apply_lint_sf(cx, overall_span, spans); - }, - SingleField::Unused => { - apply_lint_zero_fields(cx, overall_span); - }, - _ => { /* shouldn't happen */ }, - } + if let Some((SingleField::Index { index, .. }, mut spans)) = find_sf_lint(cx, patterns, &tuple_sf) { + spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, index))); + apply_lint_sf(cx, overall_span, spans); } }, _ => (), @@ -334,7 +300,6 @@ impl LateLintPass<'_> for SingleFieldPatterns { }, Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => expr_sf_lint(cx, expr.span, scrutinee, once(pat)), _ => { - // todo for maybe, other missing patterns if let Some(WhileLet { let_pat, let_expr, .. }) = WhileLet::hir(expr) { expr_sf_lint(cx, expr.span, let_expr, once(let_pat)); } diff --git a/tests/ui/single_field_pattern.rs b/tests/ui/single_field_pattern.rs index cae6b8af7bfc..7e4492693aae 100644 --- a/tests/ui/single_field_pattern.rs +++ b/tests/ui/single_field_pattern.rs @@ -5,7 +5,6 @@ struct Struct { } fn lint_struct(struct1: Struct) { - let Struct { .. } = struct1; let Struct { field1, .. } = struct1; let Struct { field1, field2: _ } = struct1; match struct1 { @@ -73,6 +72,7 @@ fn lint_array(array: [i32; 3]) { } fn ok_struct(struct1: Struct) { + let _ = struct1; let Struct { field1, field2, .. } = struct1; let Struct { field1, field2 } = struct1; match struct1 { diff --git a/tests/ui/single_field_pattern.stderr b/tests/ui/single_field_pattern.stderr index b8489e0aff3f..ffdcf89e9549 100644 --- a/tests/ui/single_field_pattern.stderr +++ b/tests/ui/single_field_pattern.stderr @@ -1,24 +1,17 @@ -error: this single-variant pattern matches no fields - --> $DIR/single_field_pattern.rs:8:5 - | -LL | let Struct { .. } = struct1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::single-field-patterns` implied by `-D warnings` - error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:9:5 + --> $DIR/single_field_pattern.rs:8:5 | LL | let Struct { field1, .. } = struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `-D clippy::single-field-patterns` implied by `-D warnings` help: try this | LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:10:5 + --> $DIR/single_field_pattern.rs:9:5 | LL | let Struct { field1, field2: _ } = struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +22,7 @@ LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:11:5 + --> $DIR/single_field_pattern.rs:10:5 | LL | / match struct1 { LL | | Struct { field1: Some(n), .. } if n >= 50 => {}, @@ -47,7 +40,7 @@ LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:16:5 + --> $DIR/single_field_pattern.rs:15:5 | LL | / match struct1 { LL | | Struct { field1: Some(n), .. } if n >= 50 => {}, @@ -65,7 +58,7 @@ LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:21:5 + --> $DIR/single_field_pattern.rs:20:5 | LL | / match struct1 { LL | | Struct { field1: Some(1), .. } => {}, @@ -85,7 +78,7 @@ LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:27:5 + --> $DIR/single_field_pattern.rs:26:5 | LL | / match struct1 { LL | | Struct { @@ -101,7 +94,7 @@ LL ~ Some(_) | None => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:32:5 + --> $DIR/single_field_pattern.rs:31:5 | LL | while let Struct { field1: Some(5), .. } = struct1 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +105,7 @@ LL | while let Some(5) = struct1.field1 {} | ~~~~~~~ ~~~~~~~~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:38:5 + --> $DIR/single_field_pattern.rs:37:5 | LL | if let Tuple(Some(x), _) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -123,7 +116,7 @@ LL | if let Some(x) = tuple.0 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:39:5 + --> $DIR/single_field_pattern.rs:38:5 | LL | if let Tuple(_, Some(y)) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -134,7 +127,7 @@ LL | if let Some(y) = tuple.1 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:40:5 + --> $DIR/single_field_pattern.rs:39:5 | LL | / match tuple { LL | | Tuple(Some(1), ..) => {}, @@ -152,7 +145,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:45:5 + --> $DIR/single_field_pattern.rs:44:5 | LL | / match tuple { LL | | Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, @@ -168,7 +161,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:52:5 + --> $DIR/single_field_pattern.rs:51:5 | LL | if let (Some(z), _) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,7 +172,7 @@ LL | if let Some(z) = tuple.0 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:53:5 + --> $DIR/single_field_pattern.rs:52:5 | LL | if let (_, Some(n)) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -190,7 +183,7 @@ LL | if let Some(n) = tuple.1 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:54:5 + --> $DIR/single_field_pattern.rs:53:5 | LL | / match tuple { LL | | (Some(1), ..) => {}, @@ -208,7 +201,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:59:5 + --> $DIR/single_field_pattern.rs:58:5 | LL | / match tuple { LL | | (Some(1) | Some(42) | Some(6082), ..) => {}, @@ -224,7 +217,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:66:5 + --> $DIR/single_field_pattern.rs:65:5 | LL | / match array { LL | | [1 | 2, ..] => {}, @@ -244,7 +237,7 @@ LL ~ e => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:72:5 + --> $DIR/single_field_pattern.rs:71:5 | LL | if let [5, ..] = array {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -254,5 +247,5 @@ help: try this LL | if let 5 = array[0] {} | ~ ~~~~~~~~ -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors From dbe9a2fab05c27113684087fe68f97a420d6bf7a Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 20:18:24 -0500 Subject: [PATCH 20/47] account for conditional compilation --- clippy_lints/src/single_field_patterns.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 73eb0445a5c3..caec7d487e74 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -21,6 +21,17 @@ declare_clippy_lint! { /// ### Why is this bad? /// It requires more information than directly accessing the field. /// + /// ### Known Issue + /// This isn't aware of conditional compilation, e.g. + /// ```rust + /// match maybe_enum { + /// Enum::Always(a) => {}, + /// #[cfg(feature = "razzle")] + /// Enum::Dazzle(a, b, c) => {}, + /// } + /// ``` + /// Supporting that would require rustc changes. + /// /// ### Example /// ```rust /// match struct1 { @@ -227,7 +238,7 @@ fn apply_lint_sf(cx: &T, span: Span, sugg: impl IntoIterator Date: Wed, 22 Dec 2021 20:26:13 -0500 Subject: [PATCH 21/47] docs --- clippy_lints/src/single_field_patterns.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index caec7d487e74..1b4e15c37697 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -1,7 +1,7 @@ #![allow(rustc::usage_of_ty_tykind)] use clippy_utils::{ - diagnostics::{multispan_sugg_with_applicability, span_lint, span_lint_and_then}, + diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}, higher::IfLetOrMatch, higher::WhileLet, source::snippet_opt, @@ -19,18 +19,10 @@ declare_clippy_lint! { /// Checks for patterns that only use a single field when they could directly access the field. /// /// ### Why is this bad? - /// It requires more information than directly accessing the field. + /// It requires more text and more information than directly accessing the field. /// - /// ### Known Issue - /// This isn't aware of conditional compilation, e.g. - /// ```rust - /// match maybe_enum { - /// Enum::Always(a) => {}, - /// #[cfg(feature = "razzle")] - /// Enum::Dazzle(a, b, c) => {}, - /// } - /// ``` - /// Supporting that would require rustc changes. + /// ### Known problems + /// This isn't aware of conditional compilation, because supporting that would require rustc changes. /// /// ### Example /// ```rust From 3aa0d1782f877b1436ed5608cce5921d4cba56ad Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 22:09:30 -0500 Subject: [PATCH 22/47] allow lint in other tests --- tests/ui/author/struct.rs | 2 +- tests/ui/collapsible_match2.rs | 3 +- tests/ui/collapsible_match2.stderr | 20 ++--- tests/ui/eta.fixed | 3 +- tests/ui/eta.rs | 3 +- tests/ui/eta.stderr | 42 +++++----- tests/ui/infallible_destructuring_match.fixed | 2 +- tests/ui/infallible_destructuring_match.rs | 2 +- tests/ui/needless_borrow_pat.rs | 2 +- tests/ui/needless_pass_by_value.rs | 3 +- tests/ui/needless_pass_by_value.stderr | 52 ++++++------ tests/ui/shadow.rs | 1 + tests/ui/shadow.stderr | 84 +++++++++---------- tests/ui/toplevel_ref_arg.fixed | 1 + tests/ui/toplevel_ref_arg.rs | 1 + tests/ui/toplevel_ref_arg.stderr | 12 +-- tests/ui/unneeded_field_pattern.rs | 1 + tests/ui/unneeded_field_pattern.stderr | 4 +- tests/ui/unneeded_wildcard_pattern.fixed | 1 + tests/ui/unneeded_wildcard_pattern.rs | 1 + tests/ui/unneeded_wildcard_pattern.stderr | 28 +++---- tests/ui/unnested_or_patterns.fixed | 7 +- tests/ui/unnested_or_patterns.rs | 7 +- tests/ui/unnested_or_patterns.stderr | 32 +++---- tests/ui/unnested_or_patterns2.fixed | 2 +- tests/ui/unnested_or_patterns2.rs | 2 +- tests/ui/while_let_on_iterator.fixed | 3 +- tests/ui/while_let_on_iterator.rs | 3 +- tests/ui/while_let_on_iterator.stderr | 42 +++++----- 29 files changed, 194 insertions(+), 172 deletions(-) diff --git a/tests/ui/author/struct.rs b/tests/ui/author/struct.rs index 5fdf3433a370..dbe3cfcf37e6 100644 --- a/tests/ui/author/struct.rs +++ b/tests/ui/author/struct.rs @@ -1,4 +1,4 @@ -#[allow(clippy::unnecessary_operation, clippy::single_match)] +#[allow(clippy::unnecessary_operation, clippy::single_match, clippy::single_field_patterns)] fn main() { struct Test { field: u32, diff --git a/tests/ui/collapsible_match2.rs b/tests/ui/collapsible_match2.rs index 542e69484276..6731c0f9de6d 100644 --- a/tests/ui/collapsible_match2.rs +++ b/tests/ui/collapsible_match2.rs @@ -3,7 +3,8 @@ clippy::needless_return, clippy::no_effect, clippy::single_match, - clippy::needless_borrow + clippy::needless_borrow, + clippy::single_field_patterns )] fn lint_cases(opt_opt: Option>, res_opt: Result, String>) { diff --git a/tests/ui/collapsible_match2.stderr b/tests/ui/collapsible_match2.stderr index 46b645aea135..c838b487b66b 100644 --- a/tests/ui/collapsible_match2.stderr +++ b/tests/ui/collapsible_match2.stderr @@ -1,5 +1,5 @@ error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:13:34 + --> $DIR/collapsible_match2.rs:14:34 | LL | Ok(val) if make() => match val { | __________________________________^ @@ -10,7 +10,7 @@ LL | | }, | = note: `-D clippy::collapsible-match` implied by `-D warnings` help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:13:16 + --> $DIR/collapsible_match2.rs:14:16 | LL | Ok(val) if make() => match val { | ^^^ replace this binding @@ -18,7 +18,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:20:24 + --> $DIR/collapsible_match2.rs:21:24 | LL | Ok(val) => match val { | ________________________^ @@ -28,7 +28,7 @@ LL | | }, | |_____________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:20:16 + --> $DIR/collapsible_match2.rs:21:16 | LL | Ok(val) => match val { | ^^^ replace this binding @@ -36,7 +36,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:34:29 + --> $DIR/collapsible_match2.rs:35:29 | LL | $pat => match $e { | _____________________________^ @@ -49,7 +49,7 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ------------------------------------------------ in this macro invocation | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:46:28 + --> $DIR/collapsible_match2.rs:47:28 | LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ^^^ ^^^^^^^ with this pattern @@ -58,7 +58,7 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:51:20 + --> $DIR/collapsible_match2.rs:52:20 | LL | Some(s) => match *s { | ____________________^ @@ -68,7 +68,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:51:14 + --> $DIR/collapsible_match2.rs:52:14 | LL | Some(s) => match *s { | ^ replace this binding @@ -76,7 +76,7 @@ LL | [n] => foo(n), | ^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:60:24 + --> $DIR/collapsible_match2.rs:61:24 | LL | Some(ref s) => match &*s { | ________________________^ @@ -86,7 +86,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:60:14 + --> $DIR/collapsible_match2.rs:61:14 | LL | Some(ref s) => match &*s { | ^^^^^ replace this binding diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index 1de79667f55f..022af70502db 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -5,7 +5,8 @@ clippy::no_effect, clippy::redundant_closure_call, clippy::needless_pass_by_value, - clippy::option_map_unit_fn + clippy::option_map_unit_fn, + clippy::single_field_patterns )] #![warn( clippy::redundant_closure, diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 86abd347baa7..1276e1e61a97 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -5,7 +5,8 @@ clippy::no_effect, clippy::redundant_closure_call, clippy::needless_pass_by_value, - clippy::option_map_unit_fn + clippy::option_map_unit_fn, + clippy::single_field_patterns )] #![warn( clippy::redundant_closure, diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 8092f04c3fc3..48d7e9e9c962 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure - --> $DIR/eta.rs:31:27 + --> $DIR/eta.rs:32:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: replace the closure with the function itself: `foo` @@ -7,19 +7,19 @@ LL | let a = Some(1u8).map(|a| foo(a)); = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:35:40 + --> $DIR/eta.rs:36:40 | LL | let _: Option> = true.then(|| vec![]); // special case vec! | ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new` error: redundant closure - --> $DIR/eta.rs:36:35 + --> $DIR/eta.rs:37:35 | LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2` error: this expression borrows a reference (`&u8`) that is immediately dereferenced by the compiler - --> $DIR/eta.rs:37:21 + --> $DIR/eta.rs:38:21 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` @@ -27,25 +27,25 @@ LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted = note: `-D clippy::needless-borrow` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:37:26 + --> $DIR/eta.rs:38:26 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below` error: redundant closure - --> $DIR/eta.rs:43:27 + --> $DIR/eta.rs:44:27 | LL | let e = Some(1u8).map(|a| divergent(a)); | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `divergent` error: redundant closure - --> $DIR/eta.rs:44:27 + --> $DIR/eta.rs:45:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> $DIR/eta.rs:90:51 + --> $DIR/eta.rs:91:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -53,79 +53,79 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:91:51 + --> $DIR/eta.rs:92:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> $DIR/eta.rs:93:42 + --> $DIR/eta.rs:94:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> $DIR/eta.rs:97:29 + --> $DIR/eta.rs:98:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> $DIR/eta.rs:98:27 + --> $DIR/eta.rs:99:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> $DIR/eta.rs:100:65 + --> $DIR/eta.rs:101:65 | LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> $DIR/eta.rs:163:22 + --> $DIR/eta.rs:164:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> $DIR/eta.rs:170:27 + --> $DIR/eta.rs:171:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> $DIR/eta.rs:175:27 + --> $DIR/eta.rs:176:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> $DIR/eta.rs:207:28 + --> $DIR/eta.rs:208:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:208:28 + --> $DIR/eta.rs:209:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:209:28 + --> $DIR/eta.rs:210:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> $DIR/eta.rs:216:21 + --> $DIR/eta.rs:217:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> $DIR/eta.rs:235:21 + --> $DIR/eta.rs:236:21 | LL | map_str_to_path(|s| s.as_ref()); | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::convert::AsRef::as_ref` diff --git a/tests/ui/infallible_destructuring_match.fixed b/tests/ui/infallible_destructuring_match.fixed index b8e40d995531..60418e619ba8 100644 --- a/tests/ui/infallible_destructuring_match.fixed +++ b/tests/ui/infallible_destructuring_match.fixed @@ -1,7 +1,7 @@ // run-rustfix #![feature(exhaustive_patterns, never_type)] #![allow(dead_code, unreachable_code, unused_variables)] -#![allow(clippy::let_and_return)] +#![allow(clippy::let_and_return, clippy::single_field_patterns)] enum SingleVariantEnum { Variant(i32), diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index 106cd438b90e..be3de028fc5e 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,7 +1,7 @@ // run-rustfix #![feature(exhaustive_patterns, never_type)] #![allow(dead_code, unreachable_code, unused_variables)] -#![allow(clippy::let_and_return)] +#![allow(clippy::let_and_return, clippy::single_field_patterns)] enum SingleVariantEnum { Variant(i32), diff --git a/tests/ui/needless_borrow_pat.rs b/tests/ui/needless_borrow_pat.rs index 04b6283da3c3..252ca6e914f4 100644 --- a/tests/ui/needless_borrow_pat.rs +++ b/tests/ui/needless_borrow_pat.rs @@ -1,7 +1,7 @@ // FIXME: run-rustfix waiting on multi-span suggestions #![warn(clippy::needless_borrow)] -#![allow(clippy::needless_borrowed_reference)] +#![allow(clippy::needless_borrowed_reference, clippy::single_field_patterns)] fn f1(_: &str) {} macro_rules! m1 { diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 5a35b100afe0..c94e758a88b1 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -4,7 +4,8 @@ clippy::single_match, clippy::redundant_pattern_matching, clippy::option_option, - clippy::redundant_clone + clippy::redundant_clone, + clippy::single_field_patterns )] use std::borrow::Borrow; diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index d960c86a9f0e..2f61ba241c45 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,5 +1,5 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:17:23 + --> $DIR/needless_pass_by_value.rs:18:23 | LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` @@ -7,55 +7,55 @@ LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec $DIR/needless_pass_by_value.rs:31:11 + --> $DIR/needless_pass_by_value.rs:32:11 | LL | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:31:22 + --> $DIR/needless_pass_by_value.rs:32:22 | LL | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:37:71 + --> $DIR/needless_pass_by_value.rs:38:71 | LL | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:49:18 + --> $DIR/needless_pass_by_value.rs:50:18 | LL | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&Option>` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:62:24 + --> $DIR/needless_pass_by_value.rs:63:24 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:62:36 + --> $DIR/needless_pass_by_value.rs:63:36 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:78:49 + --> $DIR/needless_pass_by_value.rs:79:49 | LL | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:80:18 + --> $DIR/needless_pass_by_value.rs:81:18 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:80:29 + --> $DIR/needless_pass_by_value.rs:81:29 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ @@ -70,13 +70,13 @@ LL | let _ = t.to_string(); | ~~~~~~~~~~~~~ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:80:40 + --> $DIR/needless_pass_by_value.rs:81:40 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:80:53 + --> $DIR/needless_pass_by_value.rs:81:53 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ @@ -91,85 +91,85 @@ LL | let _ = v.to_owned(); | ~~~~~~~~~~~~ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:93:12 + --> $DIR/needless_pass_by_value.rs:94:12 | LL | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:94:12 + --> $DIR/needless_pass_by_value.rs:95:12 | LL | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:103:23 + --> $DIR/needless_pass_by_value.rs:104:23 | LL | fn baz(&self, _u: U, _s: Self) {} | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:103:30 + --> $DIR/needless_pass_by_value.rs:104:30 | LL | fn baz(&self, _u: U, _s: Self) {} | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:125:24 + --> $DIR/needless_pass_by_value.rs:126:24 | LL | fn bar_copy(x: u32, y: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as `Copy` - --> $DIR/needless_pass_by_value.rs:123:1 + --> $DIR/needless_pass_by_value.rs:124:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:131:29 + --> $DIR/needless_pass_by_value.rs:132:29 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as `Copy` - --> $DIR/needless_pass_by_value.rs:123:1 + --> $DIR/needless_pass_by_value.rs:124:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:131:45 + --> $DIR/needless_pass_by_value.rs:132:45 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as `Copy` - --> $DIR/needless_pass_by_value.rs:123:1 + --> $DIR/needless_pass_by_value.rs:124:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:131:61 + --> $DIR/needless_pass_by_value.rs:132:61 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as `Copy` - --> $DIR/needless_pass_by_value.rs:123:1 + --> $DIR/needless_pass_by_value.rs:124:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:143:40 + --> $DIR/needless_pass_by_value.rs:144:40 | LL | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} | ^ help: consider taking a reference instead: `&S` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:148:20 + --> $DIR/needless_pass_by_value.rs:149:20 | LL | fn more_fun(_item: impl Club<'static, i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index 06f6949b66f5..f030b5a850ee 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,4 +1,5 @@ #![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] +#![allow(clippy::single_field_patterns)] fn shadow_same() { let x = 1; diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index dcc7d4e6b2ff..f5923e1ae538 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,254 +1,254 @@ error: `x` is shadowed by itself in `x` - --> $DIR/shadow.rs:5:9 + --> $DIR/shadow.rs:6:9 | LL | let x = x; | ^ | = note: `-D clippy::shadow-same` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:4:9 + --> $DIR/shadow.rs:5:9 | LL | let x = 1; | ^ error: `mut x` is shadowed by itself in `&x` - --> $DIR/shadow.rs:6:13 + --> $DIR/shadow.rs:7:13 | LL | let mut x = &x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:5:9 + --> $DIR/shadow.rs:6:9 | LL | let x = x; | ^ error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:7:9 + --> $DIR/shadow.rs:8:9 | LL | let x = &mut x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:6:9 + --> $DIR/shadow.rs:7:9 | LL | let mut x = &x; | ^^^^^ error: `x` is shadowed by itself in `*x` - --> $DIR/shadow.rs:8:9 + --> $DIR/shadow.rs:9:9 | LL | let x = *x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:7:9 + --> $DIR/shadow.rs:8:9 | LL | let x = &mut x; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:13:9 + --> $DIR/shadow.rs:14:9 | LL | let x = x.0; | ^ | = note: `-D clippy::shadow-reuse` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:12:9 + --> $DIR/shadow.rs:13:9 | LL | let x = ([[0]], ()); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:15:9 | LL | let x = x[0]; | ^ | note: previous binding is here - --> $DIR/shadow.rs:13:9 + --> $DIR/shadow.rs:14:9 | LL | let x = x.0; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:15:10 + --> $DIR/shadow.rs:16:10 | LL | let [x] = x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:15:9 | LL | let x = x[0]; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:16:9 + --> $DIR/shadow.rs:17:9 | LL | let x = Some(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:15:10 + --> $DIR/shadow.rs:16:10 | LL | let [x] = x; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:17:9 + --> $DIR/shadow.rs:18:9 | LL | let x = foo(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:16:9 + --> $DIR/shadow.rs:17:9 | LL | let x = Some(x); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:18:9 + --> $DIR/shadow.rs:19:9 | LL | let x = || x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:17:9 + --> $DIR/shadow.rs:18:9 | LL | let x = foo(x); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:19:9 + --> $DIR/shadow.rs:20:9 | LL | let x = Some(1).map(|_| x)?; | ^ | note: previous binding is here - --> $DIR/shadow.rs:18:9 + --> $DIR/shadow.rs:19:9 | LL | let x = || x; | ^ error: `y` is shadowed - --> $DIR/shadow.rs:21:9 + --> $DIR/shadow.rs:22:9 | LL | let y = match y { | ^ | note: previous binding is here - --> $DIR/shadow.rs:20:9 + --> $DIR/shadow.rs:21:9 | LL | let y = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:30:9 + --> $DIR/shadow.rs:31:9 | LL | let x = 2; | ^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:29:9 + --> $DIR/shadow.rs:30:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:35:13 + --> $DIR/shadow.rs:36:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:34:10 + --> $DIR/shadow.rs:35:10 | LL | fn f(x: u32) { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:40:14 + --> $DIR/shadow.rs:41:14 | LL | Some(x) => { | ^ | note: previous binding is here - --> $DIR/shadow.rs:37:9 + --> $DIR/shadow.rs:38:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:41:17 + --> $DIR/shadow.rs:42:17 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:40:14 + --> $DIR/shadow.rs:41:14 | LL | Some(x) => { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:45:17 + --> $DIR/shadow.rs:46:17 | LL | if let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:37:9 + --> $DIR/shadow.rs:38:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:46:20 + --> $DIR/shadow.rs:47:20 | LL | while let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:37:9 + --> $DIR/shadow.rs:38:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:47:15 + --> $DIR/shadow.rs:48:15 | LL | let _ = |[x]: [u32; 1]| { | ^ | note: previous binding is here - --> $DIR/shadow.rs:37:9 + --> $DIR/shadow.rs:38:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:48:13 + --> $DIR/shadow.rs:49:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:47:15 + --> $DIR/shadow.rs:48:15 | LL | let _ = |[x]: [u32; 1]| { | ^ error: `_b` shadows a previous, unrelated binding - --> $DIR/shadow.rs:85:9 + --> $DIR/shadow.rs:86:9 | LL | let _b = _a; | ^^ | note: previous binding is here - --> $DIR/shadow.rs:84:28 + --> $DIR/shadow.rs:85:28 | LL | pub async fn foo2(_a: i32, _b: i64) { | ^^ diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed index b129d95c5602..8495a9395eca 100644 --- a/tests/ui/toplevel_ref_arg.fixed +++ b/tests/ui/toplevel_ref_arg.fixed @@ -2,6 +2,7 @@ // aux-build:macro_rules.rs #![warn(clippy::toplevel_ref_arg)] +#![allow(clippy::single_field_patterns)] #[macro_use] extern crate macro_rules; diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 73eb4ff7306f..831e24f9bb50 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -2,6 +2,7 @@ // aux-build:macro_rules.rs #![warn(clippy::toplevel_ref_arg)] +#![allow(clippy::single_field_patterns)] #[macro_use] extern crate macro_rules; diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index 9c853020ab01..d1ca6e0cc5fb 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -1,5 +1,5 @@ error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:20:9 + --> $DIR/toplevel_ref_arg.rs:21:9 | LL | let ref _x = 1; | ----^^^^^^----- help: try: `let _x = &1;` @@ -7,31 +7,31 @@ LL | let ref _x = 1; = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:22:9 + --> $DIR/toplevel_ref_arg.rs:23:9 | LL | let ref _y: (&_, u8) = (&1, 2); | ----^^^^^^--------------------- help: try: `let _y: &(&_, u8) = &(&1, 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:24:9 + --> $DIR/toplevel_ref_arg.rs:25:9 | LL | let ref _z = 1 + 2; | ----^^^^^^--------- help: try: `let _z = &(1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:26:9 + --> $DIR/toplevel_ref_arg.rs:27:9 | LL | let ref mut _z = 1 + 2; | ----^^^^^^^^^^--------- help: try: `let _z = &mut (1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:31:9 + --> $DIR/toplevel_ref_arg.rs:32:9 | LL | let ref _x = vec![1, 2, 3]; | ----^^^^^^----------------- help: try: `let _x = &vec![1, 2, 3];` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:11:13 + --> $DIR/toplevel_ref_arg.rs:12:13 | LL | let ref _y = 42; | ----^^^^^^------ help: try: `let _y = &42;` diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index fa639aa70d61..6dc86fb11166 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,4 +1,5 @@ #![warn(clippy::unneeded_field_pattern)] +#![allow(clippy::single_field_patterns)] #[allow(dead_code, unused)] struct Foo { diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index b8d3c2945322..5614e82207a8 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,5 +1,5 @@ error: you matched a field with a wildcard pattern, consider using `..` instead - --> $DIR/unneeded_field_pattern.rs:14:15 + --> $DIR/unneeded_field_pattern.rs:15:15 | LL | Foo { a: _, b: 0, .. } => {}, | ^^^^ @@ -8,7 +8,7 @@ LL | Foo { a: _, b: 0, .. } => {}, = help: try with `Foo { b: 0, .. }` error: all the struct fields are matched to a wildcard pattern, consider using `..` - --> $DIR/unneeded_field_pattern.rs:16:9 + --> $DIR/unneeded_field_pattern.rs:17:9 | LL | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unneeded_wildcard_pattern.fixed b/tests/ui/unneeded_wildcard_pattern.fixed index 12c3461c9557..1d70fe6c6f8b 100644 --- a/tests/ui/unneeded_wildcard_pattern.fixed +++ b/tests/ui/unneeded_wildcard_pattern.fixed @@ -1,6 +1,7 @@ // run-rustfix #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] +#![allow(clippy::single_field_patterns)] fn main() { let t = (0, 1, 2, 3); diff --git a/tests/ui/unneeded_wildcard_pattern.rs b/tests/ui/unneeded_wildcard_pattern.rs index 4ac01d5d23b0..c9fe9068bc70 100644 --- a/tests/ui/unneeded_wildcard_pattern.rs +++ b/tests/ui/unneeded_wildcard_pattern.rs @@ -1,6 +1,7 @@ // run-rustfix #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] +#![allow(clippy::single_field_patterns)] fn main() { let t = (0, 1, 2, 3); diff --git a/tests/ui/unneeded_wildcard_pattern.stderr b/tests/ui/unneeded_wildcard_pattern.stderr index 716d9ecff89a..8a004b77e941 100644 --- a/tests/ui/unneeded_wildcard_pattern.stderr +++ b/tests/ui/unneeded_wildcard_pattern.stderr @@ -1,5 +1,5 @@ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:8:18 + --> $DIR/unneeded_wildcard_pattern.rs:9:18 | LL | if let (0, .., _) = t {}; | ^^^ help: remove it @@ -11,79 +11,79 @@ LL | #![deny(clippy::unneeded_wildcard_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:9:16 + --> $DIR/unneeded_wildcard_pattern.rs:10:16 | LL | if let (0, _, ..) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:10:13 + --> $DIR/unneeded_wildcard_pattern.rs:11:13 | LL | if let (_, .., 0) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:11:15 + --> $DIR/unneeded_wildcard_pattern.rs:12:15 | LL | if let (.., _, 0) = t {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:12:16 + --> $DIR/unneeded_wildcard_pattern.rs:13:16 | LL | if let (0, _, _, ..) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:13:18 + --> $DIR/unneeded_wildcard_pattern.rs:14:18 | LL | if let (0, .., _, _) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:22:22 + --> $DIR/unneeded_wildcard_pattern.rs:23:22 | LL | if let (0, .., _, _,) = t {}; | ^^^^^^ help: remove them error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:29:19 + --> $DIR/unneeded_wildcard_pattern.rs:30:19 | LL | if let S(0, .., _) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:30:17 + --> $DIR/unneeded_wildcard_pattern.rs:31:17 | LL | if let S(0, _, ..) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:31:14 + --> $DIR/unneeded_wildcard_pattern.rs:32:14 | LL | if let S(_, .., 0) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:32:16 + --> $DIR/unneeded_wildcard_pattern.rs:33:16 | LL | if let S(.., _, 0) = s {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:33:17 + --> $DIR/unneeded_wildcard_pattern.rs:34:17 | LL | if let S(0, _, _, ..) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:34:19 + --> $DIR/unneeded_wildcard_pattern.rs:35:19 | LL | if let S(0, .., _, _) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:43:23 + --> $DIR/unneeded_wildcard_pattern.rs:44:23 | LL | if let S(0, .., _, _,) = s {}; | ^^^^^^ help: remove them diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 46463a29e9b2..f4f2e7f21915 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -2,7 +2,12 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::upper_case_acronyms, + clippy::single_field_patterns +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index 8ce0738bfc27..fa1c73c737ab 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -2,7 +2,12 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::upper_case_acronyms, + clippy::single_field_patterns +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index de424c3fdb8f..a8ad2659c2a8 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:9:12 + --> $DIR/unnested_or_patterns.rs:14:12 | LL | if let box 0 | box 2 = Box::new(0) {} | ^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let box (0 | 2) = Box::new(0) {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:10:12 + --> $DIR/unnested_or_patterns.rs:15:12 | LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:12:12 + --> $DIR/unnested_or_patterns.rs:17:12 | LL | if let &0 | C0 | &2 = &0 {} | ^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let &(0 | 2) | C0 = &0 {} | ~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:13:12 + --> $DIR/unnested_or_patterns.rs:18:12 | LL | if let &mut 0 | &mut 2 = &mut 0 {} | ^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let &mut (0 | 2) = &mut 0 {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:14:12 + --> $DIR/unnested_or_patterns.rs:19:12 | LL | if let x @ 0 | x @ 2 = 0 {} | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let x @ (0 | 2) = 0 {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:15:12 + --> $DIR/unnested_or_patterns.rs:20:12 | LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let (0, 1 | 2 | 3) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:16:12 + --> $DIR/unnested_or_patterns.rs:21:12 | LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let (1 | 2 | 3, 0) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:17:12 + --> $DIR/unnested_or_patterns.rs:22:12 | LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | if let (x, ..) | (x, 1 | 2) = (0, 1) {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:18:12 + --> $DIR/unnested_or_patterns.rs:23:12 | LL | if let [0] | [1] = [0] {} | ^^^^^^^^^ @@ -99,7 +99,7 @@ LL | if let [0 | 1] = [0] {} | ~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:19:12 + --> $DIR/unnested_or_patterns.rs:24:12 | LL | if let [x, 0] | [x, 1] = [0, 1] {} | ^^^^^^^^^^^^^^^ @@ -110,7 +110,7 @@ LL | if let [x, 0 | 1] = [0, 1] {} | ~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:20:12 + --> $DIR/unnested_or_patterns.rs:25:12 | LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | if let [x, 0 | 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:21:12 + --> $DIR/unnested_or_patterns.rs:26:12 | LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | if let [x, ..] | [x, 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:23:12 + --> $DIR/unnested_or_patterns.rs:28:12 | LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | if let TS(0 | 1, x) = TS(0, 0) {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:24:12 + --> $DIR/unnested_or_patterns.rs:29:12 | LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | if let TS(1 | 2 | 3, 0) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:25:12 + --> $DIR/unnested_or_patterns.rs:30:12 | LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:30:12 + --> $DIR/unnested_or_patterns.rs:35:12 | LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed index d3539d798157..780f5b0a788f 100644 --- a/tests/ui/unnested_or_patterns2.fixed +++ b/tests/ui/unnested_or_patterns2.fixed @@ -2,7 +2,7 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::single_field_patterns)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs index 9cea5cdea699..47ac80c020e6 100644 --- a/tests/ui/unnested_or_patterns2.rs +++ b/tests/ui/unnested_or_patterns2.rs @@ -2,7 +2,7 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::single_field_patterns)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index 1e74ad2de655..ff17010fb9a7 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -6,7 +6,8 @@ unreachable_code, unused_mut, dead_code, - clippy::equatable_if_let + clippy::equatable_if_let, + clippy::single_field_patterns )] fn base() { diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 69cb636cee82..ddbb17cf9efa 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -6,7 +6,8 @@ unreachable_code, unused_mut, dead_code, - clippy::equatable_if_let + clippy::equatable_if_let, + clippy::single_field_patterns )] fn base() { diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index 1a11ba26eef0..e0b664d16759 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:14:5 + --> $DIR/while_let_on_iterator.rs:15:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,85 +7,85 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:19:5 + --> $DIR/while_let_on_iterator.rs:20:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:24:5 + --> $DIR/while_let_on_iterator.rs:25:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:100:9 + --> $DIR/while_let_on_iterator.rs:101:9 | LL | while let Some([..]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:107:9 + --> $DIR/while_let_on_iterator.rs:108:9 | LL | while let Some([_x]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:120:9 + --> $DIR/while_let_on_iterator.rs:121:9 | LL | while let Some(x @ [_]) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:140:9 + --> $DIR/while_let_on_iterator.rs:141:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:197:9 + --> $DIR/while_let_on_iterator.rs:198:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:208:5 + --> $DIR/while_let_on_iterator.rs:209:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:210:9 + --> $DIR/while_let_on_iterator.rs:211:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:219:9 + --> $DIR/while_let_on_iterator.rs:220:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:228:9 + --> $DIR/while_let_on_iterator.rs:229:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:245:9 + --> $DIR/while_let_on_iterator.rs:246:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:260:13 + --> $DIR/while_let_on_iterator.rs:261:13 | LL | while let Some(i) = self.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()` error: manual `!RangeInclusive::contains` implementation - --> $DIR/while_let_on_iterator.rs:261:20 + --> $DIR/while_let_on_iterator.rs:262:20 | LL | if i < 3 || i > 7 { | ^^^^^^^^^^^^^^ help: use: `!(3..=7).contains(&i)` @@ -93,37 +93,37 @@ LL | if i < 3 || i > 7 { = note: `-D clippy::manual-range-contains` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:292:13 + --> $DIR/while_let_on_iterator.rs:293:13 | LL | while let Some(i) = self.0.0.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:321:5 + --> $DIR/while_let_on_iterator.rs:322:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:333:9 + --> $DIR/while_let_on_iterator.rs:334:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:347:5 + --> $DIR/while_let_on_iterator.rs:348:5 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:358:5 + --> $DIR/while_let_on_iterator.rs:359:5 | LL | while let Some(x) = it.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:377:5 + --> $DIR/while_let_on_iterator.rs:378:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` From 5b50e5e1d109c6732fe952ab08429d2cea8b79c9 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 22:13:00 -0500 Subject: [PATCH 23/47] fix self-lints in my code --- clippy_lints/src/single_field_patterns.rs | 38 ++++++++++++----------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 1b4e15c37697..df07a9f11955 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -7,7 +7,7 @@ use clippy_utils::{ source::snippet_opt, }; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Expr, Local, MatchSource, Pat, PatKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -56,11 +56,10 @@ enum SingleField { impl PartialEq for SingleField { fn eq(&self, other: &Self) -> bool { - use SingleField::*; match (self, other) { - (Id { id: id1, .. }, Id { id: id2, .. }) => id1 == id2, - (Index { index: index1, .. }, Index { index: index2, .. }) => index1 == index2, - (Unused, Unused) => true, + (SingleField::Id { id: id1, .. }, SingleField::Id { id: id2, .. }) => id1 == id2, + (SingleField::Index { index: index1, .. }, SingleField::Index { index: index2, .. }) => index1 == index2, + (SingleField::Unused, SingleField::Unused) => true, _ => false, } } @@ -127,7 +126,7 @@ fn tuple_sf(pat: &PatKind<'_>) -> Option { fn slice_sf(pat: &PatKind<'_>) -> Option { if let PatKind::Slice(before, dots, after) = pat { - if dots.is_none() || after.len() == 0 { + if dots.is_none() || after.is_empty() { return get_sf(before.iter().enumerate()); } } @@ -157,7 +156,7 @@ impl>> Iterator for FlatPatterns<'hir, I> { type Item = &'hir Pat<'hir>; fn next(&mut self) -> Option { - if self.stack.len() == 0 { + if self.stack.is_empty() { if let Some(pat) = self.patterns.next() { self.stack.push(pat); } else { @@ -255,7 +254,7 @@ fn typed_sf_lint<'hir, T: LintContext>( match field { SingleField::Id { id, .. } => format!("{}.{}", scrutinee_name, id.as_str()), SingleField::Index { index, .. } => format!("{}.{}", scrutinee_name, index), - _ => return, + SingleField::Unused => return, }, )); apply_lint_sf(cx, overall_span, spans); @@ -314,16 +313,19 @@ impl LateLintPass<'_> for SingleFieldPatterns { if stmt.span.from_expansion() { return; } - if let StmtKind::Local(Local { pat, init, .. }) = stmt.kind { - if let Some(scrutinee) = init { - typed_sf_lint( - cx, - stmt.span, - scrutinee.span, - cx.typeck_results().expr_ty(scrutinee).kind(), - once(*pat), - ); - } + if let StmtKind::Local(Local { + pat, + init: Some(scrutinee), + .. + }) = stmt.kind + { + typed_sf_lint( + cx, + stmt.span, + scrutinee.span, + cx.typeck_results().expr_ty(scrutinee).kind(), + once(*pat), + ); } } } From d9670e3b69b677fd14f7c872e3b7e514b1b4af5e Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 22:13:58 -0500 Subject: [PATCH 24/47] correct uitest name --- tests/ui/{single_field_pattern.rs => single_field_patterns.rs} | 0 .../{single_field_pattern.stderr => single_field_patterns.stderr} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{single_field_pattern.rs => single_field_patterns.rs} (100%) rename tests/ui/{single_field_pattern.stderr => single_field_patterns.stderr} (100%) diff --git a/tests/ui/single_field_pattern.rs b/tests/ui/single_field_patterns.rs similarity index 100% rename from tests/ui/single_field_pattern.rs rename to tests/ui/single_field_patterns.rs diff --git a/tests/ui/single_field_pattern.stderr b/tests/ui/single_field_patterns.stderr similarity index 100% rename from tests/ui/single_field_pattern.stderr rename to tests/ui/single_field_patterns.stderr From 707b2ea8fc427d9b9391159c1e92b5575d60d7cb Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 22:21:56 -0500 Subject: [PATCH 25/47] bless rename --- tests/ui/single_field_patterns.stderr | 34 +++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/ui/single_field_patterns.stderr b/tests/ui/single_field_patterns.stderr index ffdcf89e9549..3c6eb809b580 100644 --- a/tests/ui/single_field_patterns.stderr +++ b/tests/ui/single_field_patterns.stderr @@ -1,5 +1,5 @@ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:8:5 + --> $DIR/single_field_patterns.rs:8:5 | LL | let Struct { field1, .. } = struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:9:5 + --> $DIR/single_field_patterns.rs:9:5 | LL | let Struct { field1, field2: _ } = struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:10:5 + --> $DIR/single_field_patterns.rs:10:5 | LL | / match struct1 { LL | | Struct { field1: Some(n), .. } if n >= 50 => {}, @@ -40,7 +40,7 @@ LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:15:5 + --> $DIR/single_field_patterns.rs:15:5 | LL | / match struct1 { LL | | Struct { field1: Some(n), .. } if n >= 50 => {}, @@ -58,7 +58,7 @@ LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:20:5 + --> $DIR/single_field_patterns.rs:20:5 | LL | / match struct1 { LL | | Struct { field1: Some(1), .. } => {}, @@ -78,7 +78,7 @@ LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:26:5 + --> $DIR/single_field_patterns.rs:26:5 | LL | / match struct1 { LL | | Struct { @@ -94,7 +94,7 @@ LL ~ Some(_) | None => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:31:5 + --> $DIR/single_field_patterns.rs:31:5 | LL | while let Struct { field1: Some(5), .. } = struct1 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | while let Some(5) = struct1.field1 {} | ~~~~~~~ ~~~~~~~~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:37:5 + --> $DIR/single_field_patterns.rs:37:5 | LL | if let Tuple(Some(x), _) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,7 +116,7 @@ LL | if let Some(x) = tuple.0 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:38:5 + --> $DIR/single_field_patterns.rs:38:5 | LL | if let Tuple(_, Some(y)) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | if let Some(y) = tuple.1 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:39:5 + --> $DIR/single_field_patterns.rs:39:5 | LL | / match tuple { LL | | Tuple(Some(1), ..) => {}, @@ -145,7 +145,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:44:5 + --> $DIR/single_field_patterns.rs:44:5 | LL | / match tuple { LL | | Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, @@ -161,7 +161,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:51:5 + --> $DIR/single_field_patterns.rs:51:5 | LL | if let (Some(z), _) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -172,7 +172,7 @@ LL | if let Some(z) = tuple.0 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:52:5 + --> $DIR/single_field_patterns.rs:52:5 | LL | if let (_, Some(n)) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -183,7 +183,7 @@ LL | if let Some(n) = tuple.1 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:53:5 + --> $DIR/single_field_patterns.rs:53:5 | LL | / match tuple { LL | | (Some(1), ..) => {}, @@ -201,7 +201,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:58:5 + --> $DIR/single_field_patterns.rs:58:5 | LL | / match tuple { LL | | (Some(1) | Some(42) | Some(6082), ..) => {}, @@ -217,7 +217,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:65:5 + --> $DIR/single_field_patterns.rs:65:5 | LL | / match array { LL | | [1 | 2, ..] => {}, @@ -237,7 +237,7 @@ LL ~ e => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_pattern.rs:71:5 + --> $DIR/single_field_patterns.rs:71:5 | LL | if let [5, ..] = array {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ From 7f52f2457eaee64304429826fd6a234c5b17751e Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 22:41:30 -0500 Subject: [PATCH 26/47] remove comment --- clippy_lints/src/single_field_patterns.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index df07a9f11955..26b5f678a66b 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -188,10 +188,6 @@ fn find_sf_lint<'hir, T: LintContext>( }, ) }); - // if we can somehow replace this operation and this vec with an iterator, that'd be nice - // this is slightly difficult because it's a two-part operation - // prior = iter.as_ref().find_partition(...first id...) - // latter = iter. let mut spans = Vec::<(Span, String)>::new(); let mut the_one: Option = None; for (target, sf) in fields { From 1ccef1498a362a6a08b380b4a231129bd75dbc6e Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 22:49:38 -0500 Subject: [PATCH 27/47] internal lints --- clippy_lints/src/comparison_chain.rs | 2 +- clippy_lints/src/dereference.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 4 ++-- clippy_lints/src/manual_map.rs | 2 +- clippy_lints/src/manual_strip.rs | 2 +- clippy_lints/src/open_options.rs | 6 +----- clippy_lints/src/utils/internal_lints/metadata_collector.rs | 6 +++--- clippy_lints/src/write.rs | 4 ++-- 8 files changed, 12 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 399d11472b09..a75d0be60d4f 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain { } // Check that there exists at least one explicit else condition - let (conds, _) = if_sequence(expr); + let conds = if_sequence(expr).0; if conds.len() < 2 { return; } diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index fa2b348591be..7ca44d0d5f06 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -508,7 +508,7 @@ fn report(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: Stat let mut app = Applicability::MachineApplicable; let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); let ty = cx.typeck_results().expr_ty(expr); - let (_, ref_count) = peel_mid_ty_refs(ty); + let ref_count = peel_mid_ty_refs(ty).1; let deref_str = if ty_changed_count >= ref_count && ref_count != 0 { // a deref call changing &T -> &U requires two deref operators the first time // this occurs. One to remove the reference, a second to call the deref impl. diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 9ead4bb27a58..14b8787ba8fb 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { let const_range = to_const_range(cx, range, size); - if let (Some(start), _) = const_range { + if let Some(start) = const_range.0 { if start > size { span_lint( cx, @@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { } } - if let (_, Some(end)) = const_range { + if let Some(end) = const_range.1 { if end > size { span_lint( cx, diff --git a/clippy_lints/src/manual_map.rs b/clippy_lints/src/manual_map.rs index 4d8ad566e6b1..21423a6c91ee 100644 --- a/clippy_lints/src/manual_map.rs +++ b/clippy_lints/src/manual_map.rs @@ -150,7 +150,7 @@ impl LateLintPass<'_> for ManualMap { // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; - let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); + let scrutinee_str = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app).0; let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX { format!("({})", scrutinee_str) diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index f8e28f1671f0..7ddaf19d35a4 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -146,7 +146,7 @@ fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx E // Returns the length of the `expr` if it's a constant string or char. fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { - let (value, _) = constant(cx, cx.typeck_results(), expr)?; + let value = constant(cx, cx.typeck_results(), expr)?.0; match value { Constant::Str(value) => Some(value.len() as u128), Constant::Char(value) => Some(value.len_utf8() as u128), diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 2c77100bdcfc..f9fd6c17f9d3 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -67,11 +67,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { let argument_option = match arguments[1].kind { ExprKind::Lit(ref span) => { - if let Spanned { - node: LitKind::Bool(lit), - .. - } = *span - { + if let LitKind::Bool(lit) = span.node { if lit { Argument::True } else { Argument::False } } else { // The function is called with a literal which is not a boolean literal. diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 8051c58bad7a..2e81e5e54c06 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -677,7 +677,7 @@ fn extract_emission_info<'hir>( let mut multi_part = false; for arg in args { - let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg)); + let arg_ty = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg)).0; if match_type(cx, arg_ty, &paths::LINT) { // If we found the lint arg, extract the lint name @@ -810,7 +810,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { } fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); + let expr_ty = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)).0; if_chain! { if match_type(self.cx, expr_ty, &paths::APPLICABILITY); @@ -900,7 +900,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> { } }, ExprKind::MethodCall(path, _path_span, arg, _arg_span) => { - let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&arg[0])); + let self_ty = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&arg[0])).0; if match_type(self.cx, self_ty, &paths::DIAGNOSTIC_BUILDER) { let called_method = path.ident.name.as_str().to_string(); for (method_name, is_multi_part) in &SUGGESTION_DIAGNOSTIC_BUILDER_METHODS { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index c90fca24ad48..7be10743724f 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -624,7 +624,7 @@ impl Write { } fn lint_println_empty_string(&self, cx: &EarlyContext<'_>, mac: &MacCall) { - if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) { + if let Some(fmt_str) = self.check_tts(cx, mac.args.inner_tokens(), false).0 { if fmt_str.symbol == kw::Empty { let name = mac.path.segments[0].ident.name; span_lint_and_sugg( @@ -641,7 +641,7 @@ impl Write { } fn lint_print_with_newline(&self, cx: &EarlyContext<'_>, mac: &MacCall) { - if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) { + if let Some(fmt_str) = self.check_tts(cx, mac.args.inner_tokens(), false).0 { if check_newlines(&fmt_str) { let name = mac.path.segments[0].ident.name; let suggested = format!("{}ln", name); From beb68eabc8a0ec0f3047ea805ffc2cf3a05667f4 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 23:11:11 -0500 Subject: [PATCH 28/47] handle dereferencing; refactor --- clippy_lints/src/single_field_patterns.rs | 55 +++++++++-------------- tests/ui/single_field_patterns.rs | 5 +++ tests/ui/single_field_patterns.stderr | 33 +++++++++----- 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 26b5f678a66b..8d681ae2ca3e 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -7,7 +7,7 @@ use clippy_utils::{ source::snippet_opt, }; use rustc_errors::Applicability; -use rustc_hir::{Expr, Local, MatchSource, Pat, PatKind, Stmt, StmtKind}; +use rustc_hir::{Expr, ExprKind, Local, MatchSource, Pat, PatKind, Stmt, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -230,23 +230,29 @@ fn apply_lint_sf(cx: &T, span: Span, sugg: impl IntoIterator( - cx: &T, +fn remove_deref<'a>(mut scrutinee: &'a Expr<'a>) -> &'a Expr<'a> { + while let ExprKind::Unary(UnOp::Deref, expr) = scrutinee.kind { + scrutinee = expr; + } + scrutinee +} + +fn typed_sf_lint<'hir>( + cx: &LateContext<'_>, overall_span: Span, - scrutinee_span: Span, - ty: &ty::TyKind<'_>, + scrutinee: &Expr<'_>, patterns: impl Iterator>, ) { - let scrutinee_name = if let Some(name) = snippet_opt(cx, scrutinee_span) { + let scrutinee_name = if let Some(name) = snippet_opt(cx, remove_deref(scrutinee).span) { name } else { return; }; - match ty { + match cx.typeck_results().expr_ty(scrutinee).kind() { ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.variants.raw.len() == 1 => { if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &struct_sf) { spans.push(( - scrutinee_span, + scrutinee.span, match field { SingleField::Id { id, .. } => format!("{}.{}", scrutinee_name, id.as_str()), SingleField::Index { index, .. } => format!("{}.{}", scrutinee_name, index), @@ -258,13 +264,13 @@ fn typed_sf_lint<'hir, T: LintContext>( }, ty::TyKind::Array(..) => { if let Some((SingleField::Index { index, .. }, mut spans)) = find_sf_lint(cx, patterns, &slice_sf) { - spans.push((scrutinee_span, format!("{}[{}]", scrutinee_name, index))); + spans.push((scrutinee.span, format!("{}[{}]", scrutinee_name, index))); apply_lint_sf(cx, overall_span, spans); } }, ty::TyKind::Tuple(..) => { if let Some((SingleField::Index { index, .. }, mut spans)) = find_sf_lint(cx, patterns, &tuple_sf) { - spans.push((scrutinee_span, format!("{}.{}", scrutinee_name, index))); + spans.push((scrutinee.span, format!("{}.{}", scrutinee_name, index))); apply_lint_sf(cx, overall_span, spans); } }, @@ -272,21 +278,6 @@ fn typed_sf_lint<'hir, T: LintContext>( }; } -fn expr_sf_lint<'hir>( - cx: &LateContext<'_>, - overall_span: Span, - scrutinee: &Expr<'_>, - patterns: impl Iterator>, -) { - typed_sf_lint( - cx, - overall_span, - scrutinee.span, - cx.typeck_results().expr_ty(scrutinee).kind(), - patterns, - ); -} - impl LateLintPass<'_> for SingleFieldPatterns { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if expr.span.from_expansion() { @@ -294,12 +285,12 @@ impl LateLintPass<'_> for SingleFieldPatterns { } match IfLetOrMatch::parse(cx, expr) { Some(IfLetOrMatch::Match(scrutinee, arms, MatchSource::Normal)) => { - expr_sf_lint(cx, expr.span, scrutinee, arms.iter().map(|arm| arm.pat)); + typed_sf_lint(cx, expr.span, scrutinee, arms.iter().map(|arm| arm.pat)); }, - Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => expr_sf_lint(cx, expr.span, scrutinee, once(pat)), + Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => typed_sf_lint(cx, expr.span, scrutinee, once(pat)), _ => { if let Some(WhileLet { let_pat, let_expr, .. }) = WhileLet::hir(expr) { - expr_sf_lint(cx, expr.span, let_expr, once(let_pat)); + typed_sf_lint(cx, expr.span, let_expr, once(let_pat)); } }, }; @@ -315,13 +306,7 @@ impl LateLintPass<'_> for SingleFieldPatterns { .. }) = stmt.kind { - typed_sf_lint( - cx, - stmt.span, - scrutinee.span, - cx.typeck_results().expr_ty(scrutinee).kind(), - once(*pat), - ); + typed_sf_lint(cx, stmt.span, scrutinee, once(*pat)); } } } diff --git a/tests/ui/single_field_patterns.rs b/tests/ui/single_field_patterns.rs index 7e4492693aae..01703ecefc4f 100644 --- a/tests/ui/single_field_patterns.rs +++ b/tests/ui/single_field_patterns.rs @@ -31,6 +31,11 @@ fn lint_struct(struct1: Struct) { while let Struct { field1: Some(5), .. } = struct1 {} } +fn lint_ref(struct1: &&Struct) { + // this should suggest struct1.field1, NOT **struct1.field1 + let Struct { field1, .. } = **struct1; +} + struct Tuple(Option, Option); fn lint_tuple_struct(tuple: Tuple) { diff --git a/tests/ui/single_field_patterns.stderr b/tests/ui/single_field_patterns.stderr index 3c6eb809b580..6d07f590bc78 100644 --- a/tests/ui/single_field_patterns.stderr +++ b/tests/ui/single_field_patterns.stderr @@ -105,7 +105,18 @@ LL | while let Some(5) = struct1.field1 {} | ~~~~~~~ ~~~~~~~~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:37:5 + --> $DIR/single_field_patterns.rs:36:5 + | +LL | let Struct { field1, .. } = **struct1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | let field1 = struct1.field1; + | ~~~~~~ ~~~~~~~~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_patterns.rs:42:5 | LL | if let Tuple(Some(x), _) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,7 +127,7 @@ LL | if let Some(x) = tuple.0 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:38:5 + --> $DIR/single_field_patterns.rs:43:5 | LL | if let Tuple(_, Some(y)) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,7 +138,7 @@ LL | if let Some(y) = tuple.1 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:39:5 + --> $DIR/single_field_patterns.rs:44:5 | LL | / match tuple { LL | | Tuple(Some(1), ..) => {}, @@ -145,7 +156,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:44:5 + --> $DIR/single_field_patterns.rs:49:5 | LL | / match tuple { LL | | Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, @@ -161,7 +172,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:51:5 + --> $DIR/single_field_patterns.rs:56:5 | LL | if let (Some(z), _) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -172,7 +183,7 @@ LL | if let Some(z) = tuple.0 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:52:5 + --> $DIR/single_field_patterns.rs:57:5 | LL | if let (_, Some(n)) = tuple {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -183,7 +194,7 @@ LL | if let Some(n) = tuple.1 {} | ~~~~~~~ ~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:53:5 + --> $DIR/single_field_patterns.rs:58:5 | LL | / match tuple { LL | | (Some(1), ..) => {}, @@ -201,7 +212,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:58:5 + --> $DIR/single_field_patterns.rs:63:5 | LL | / match tuple { LL | | (Some(1) | Some(42) | Some(6082), ..) => {}, @@ -217,7 +228,7 @@ LL ~ a => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:65:5 + --> $DIR/single_field_patterns.rs:70:5 | LL | / match array { LL | | [1 | 2, ..] => {}, @@ -237,7 +248,7 @@ LL ~ e => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:71:5 + --> $DIR/single_field_patterns.rs:76:5 | LL | if let [5, ..] = array {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -247,5 +258,5 @@ help: try this LL | if let 5 = array[0] {} | ~ ~~~~~~~~ -error: aborting due to 17 previous errors +error: aborting due to 18 previous errors From aa76b405f796f2ae62a774d3168b4b61750b9e7c Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 23:30:04 -0500 Subject: [PATCH 29/47] refactor --- clippy_lints/src/single_field_patterns.rs | 26 +++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 8d681ae2ca3e..07906cf707b7 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -47,6 +47,8 @@ declare_clippy_lint! { } declare_lint_pass!(SingleFieldPatterns => [SINGLE_FIELD_PATTERNS]); +/// This represents 0 or 1 fields being used. Where more may be used, I use Option +/// where None represents the absence of a lint #[derive(Debug, Clone, Copy)] enum SingleField { Id { id: Ident, pattern: Span }, @@ -95,10 +97,11 @@ fn get_sf<'a, ID: IntoSingleField>(mut iter: impl Iterator], leap: &Option) -> Option { +fn inner_tuple_sf(pats: &[Pat<'_>], leap: Option) -> Option { get_sf(pats.iter().enumerate()).and_then(|field| { if let SingleField::Index { index, .. } = field { - if let Some(leap_index) = *leap { + // exclude (.., x) type patterns + if let Some(leap_index) = leap { if leap_index <= index { return None; } @@ -109,7 +112,7 @@ fn inner_tuple_sf(pats: &&[Pat<'_>], leap: &Option) -> Option) -> Option { - match pat { + match *pat { PatKind::Struct(_, pats, _) => get_sf(pats.iter().map(|field| (field.ident, field.pat))), PatKind::TupleStruct(_, pats, leap) => inner_tuple_sf(pats, leap), _ => None, @@ -117,7 +120,7 @@ fn struct_sf(pat: &PatKind<'_>) -> Option { } fn tuple_sf(pat: &PatKind<'_>) -> Option { - if let PatKind::Tuple(pats, leap) = pat { + if let PatKind::Tuple(pats, leap) = *pat { inner_tuple_sf(pats, leap) } else { None @@ -126,6 +129,7 @@ fn tuple_sf(pat: &PatKind<'_>) -> Option { fn slice_sf(pat: &PatKind<'_>) -> Option { if let PatKind::Slice(before, dots, after) = pat { + // exclude [.., x] type patterns if dots.is_none() || after.is_empty() { return get_sf(before.iter().enumerate()); } @@ -134,7 +138,7 @@ fn slice_sf(pat: &PatKind<'_>) -> Option { } /// This handles recursive patterns and flattens them out lazily -/// That basically just means handling stuff like 1 | (2 | 9) | 3..5 +/// e.g. 1 | (2 | 9) | 3..5 struct FlatPatterns<'hir, I> where I: Iterator>, @@ -169,7 +173,7 @@ impl>> Iterator for FlatPatterns<'hir, I> { _ => return Some(pat), } } - None + unreachable!("Or always has 2 patterns, so one of the prior returns must return"); } } @@ -237,7 +241,7 @@ fn remove_deref<'a>(mut scrutinee: &'a Expr<'a>) -> &'a Expr<'a> { scrutinee } -fn typed_sf_lint<'hir>( +fn lint_sf<'hir>( cx: &LateContext<'_>, overall_span: Span, scrutinee: &Expr<'_>, @@ -285,12 +289,12 @@ impl LateLintPass<'_> for SingleFieldPatterns { } match IfLetOrMatch::parse(cx, expr) { Some(IfLetOrMatch::Match(scrutinee, arms, MatchSource::Normal)) => { - typed_sf_lint(cx, expr.span, scrutinee, arms.iter().map(|arm| arm.pat)); + lint_sf(cx, expr.span, scrutinee, arms.iter().map(|arm| arm.pat)); }, - Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => typed_sf_lint(cx, expr.span, scrutinee, once(pat)), + Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => lint_sf(cx, expr.span, scrutinee, once(pat)), _ => { if let Some(WhileLet { let_pat, let_expr, .. }) = WhileLet::hir(expr) { - typed_sf_lint(cx, expr.span, let_expr, once(let_pat)); + lint_sf(cx, expr.span, let_expr, once(let_pat)); } }, }; @@ -306,7 +310,7 @@ impl LateLintPass<'_> for SingleFieldPatterns { .. }) = stmt.kind { - typed_sf_lint(cx, stmt.span, scrutinee, once(*pat)); + lint_sf(cx, stmt.span, scrutinee, once(*pat)); } } } From 2dc1acf3d1e8217ca30f5e3a8a0839e7349a28cb Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 23:35:42 -0500 Subject: [PATCH 30/47] inline unnecessary type params --- clippy_lints/src/single_field_patterns.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 07906cf707b7..e0c640827f20 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -8,7 +8,7 @@ use clippy_utils::{ }; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Local, MatchSource, Pat, PatKind, Stmt, StmtKind, UnOp}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{symbol::Ident, Span}; @@ -177,8 +177,8 @@ impl>> Iterator for FlatPatterns<'hir, I> { } } -fn find_sf_lint<'hir, T: LintContext>( - cx: &T, +fn find_sf_lint<'hir>( + cx: &LateContext<'_>, patterns: impl Iterator>, leaf_sf: &impl Fn(&PatKind<'hir>) -> Option, ) -> Option<(SingleField, Vec<(Span, String)>)> { @@ -222,7 +222,7 @@ fn find_sf_lint<'hir, T: LintContext>( the_one.map(|one| (one, spans)) } -fn apply_lint_sf(cx: &T, span: Span, sugg: impl IntoIterator) { +fn apply_lint_sf(cx: &LateContext<'_>, span: Span, sugg: impl IntoIterator) { span_lint_and_then( cx, SINGLE_FIELD_PATTERNS, From 4de5addadd1d035a9785583c528426bd89a3271b Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 23:38:45 -0500 Subject: [PATCH 31/47] yay we can handle enums after all --- clippy_lints/src/single_field_patterns.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index e0c640827f20..628aa6dd557a 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -21,9 +21,6 @@ declare_clippy_lint! { /// ### Why is this bad? /// It requires more text and more information than directly accessing the field. /// - /// ### Known problems - /// This isn't aware of conditional compilation, because supporting that would require rustc changes. - /// /// ### Example /// ```rust /// match struct1 { @@ -253,7 +250,7 @@ fn lint_sf<'hir>( return; }; match cx.typeck_results().expr_ty(scrutinee).kind() { - ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.variants.raw.len() == 1 => { + ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if !def.is_enum() => { if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &struct_sf) { spans.push(( scrutinee.span, From 79a3e7aacd52e243b547db2aa9e7669a223c7d54 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Wed, 22 Dec 2021 23:55:58 -0500 Subject: [PATCH 32/47] don't handle unions --- clippy_lints/src/single_field_patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 628aa6dd557a..23b6e3fddf40 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -250,7 +250,7 @@ fn lint_sf<'hir>( return; }; match cx.typeck_results().expr_ty(scrutinee).kind() { - ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if !def.is_enum() => { + ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.is_struct() => { if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &struct_sf) { spans.push(( scrutinee.span, From 75a71897902e3b6dd651c2fdefa9b140efd88d9e Mon Sep 17 00:00:00 2001 From: hahohihu Date: Thu, 23 Dec 2021 00:00:17 -0500 Subject: [PATCH 33/47] comment --- clippy_lints/src/single_field_patterns.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 23b6e3fddf40..62e5e0c82ed5 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -232,6 +232,7 @@ fn apply_lint_sf(cx: &LateContext<'_>, span: Span, sugg: impl IntoIterator(mut scrutinee: &'a Expr<'a>) -> &'a Expr<'a> { + // it would be wrong to convert something like `if let (x, _) = *a` into `if let x = *a.0` while let ExprKind::Unary(UnOp::Deref, expr) = scrutinee.kind { scrutinee = expr; } From bf4029847e75bdab50737f6ea06c763f9d4f71b6 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Thu, 23 Dec 2021 00:15:20 -0500 Subject: [PATCH 34/47] correct applicability --- clippy_lints/src/single_field_patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 62e5e0c82ed5..f7f29ef77433 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -226,7 +226,7 @@ fn apply_lint_sf(cx: &LateContext<'_>, span: Span, sugg: impl IntoIterator Date: Thu, 23 Dec 2021 00:22:57 -0500 Subject: [PATCH 35/47] fix lints --- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/open_options.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 2cdd59c56919..fdcae4974ef3 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -547,7 +547,7 @@ fn check_doc<'a, Events: Iterator, Range { diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index f9fd6c17f9d3..3ec75abaaf21 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -5,7 +5,7 @@ use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::{Span, Spanned}; +use rustc_span::source_map::Span; declare_clippy_lint! { /// ### What it does From e9eea7ea78e611498d4a0d99c0362bec62d19ef0 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Thu, 23 Dec 2021 01:22:35 -0500 Subject: [PATCH 36/47] fix doctest --- clippy_lints/src/single_field_patterns.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index f7f29ef77433..e83c41e66cee 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -23,19 +23,24 @@ declare_clippy_lint! { /// /// ### Example /// ```rust + /// # struct Struct { + /// # field1: Option, + /// # field2: Option, + /// # } + /// # fn foo(struct1: Struct) { + /// // bad: /// match struct1 { /// Struct { field1: Some(n), .. } if n >= 50 => {}, /// Struct { field1: None, .. } => {}, /// _ => {}, /// } - /// ``` - /// Use instead: - /// ```rust + /// // better: /// match struct1.field1 { /// Some(n) if n >= 50 => {}, /// None => {}, /// _ => {}, /// } + /// # } /// ``` #[clippy::version = "1.59.0"] pub SINGLE_FIELD_PATTERNS, From e1d867aa069db424b89aa1f634a1f0e48e8fa61c Mon Sep 17 00:00:00 2001 From: hahohihu Date: Thu, 23 Dec 2021 21:27:29 -0500 Subject: [PATCH 37/47] ignore macros --- clippy_lints/src/single_field_patterns.rs | 9 +++++++++ tests/ui/single_field_patterns.rs | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index e83c41e66cee..a4758f033e99 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -89,6 +89,9 @@ fn get_sf<'a, ID: IntoSingleField>(mut iter: impl Iterator { + if pat.span.from_expansion() { + return None; + } if iter.all(|(_, other)| matches!(other.kind, PatKind::Wild)) { Some(index.into_sf(pat.span)) } else { @@ -197,6 +200,9 @@ fn find_sf_lint<'hir>( let mut spans = Vec::<(Span, String)>::new(); let mut the_one: Option = None; for (target, sf) in fields { + if target.from_expansion() { + return None; + } if let Some(sf) = sf { match sf { SingleField::Unused => { @@ -250,6 +256,9 @@ fn lint_sf<'hir>( scrutinee: &Expr<'_>, patterns: impl Iterator>, ) { + if scrutinee.span.from_expansion() { + return; + } let scrutinee_name = if let Some(name) = snippet_opt(cx, remove_deref(scrutinee).span) { name } else { diff --git a/tests/ui/single_field_patterns.rs b/tests/ui/single_field_patterns.rs index 01703ecefc4f..85577e4e04e0 100644 --- a/tests/ui/single_field_patterns.rs +++ b/tests/ui/single_field_patterns.rs @@ -76,6 +76,24 @@ fn lint_array(array: [i32; 3]) { if let [5, ..] = array {} } +macro_rules! mac { + () => { + (1, 2, 3) + }; +} + +macro_rules! pat { + ($id:ident) => { + (_, $id, _) + }; +} + +fn ok_macro() { + let (_, a, _) = mac!(); + let pat!(a) = (1, 2, 3); + let (pat!(a), _) = (mac!(), mac!()); +} + fn ok_struct(struct1: Struct) { let _ = struct1; let Struct { field1, field2, .. } = struct1; From 5b7e4e9316580c9ecd54674cb707ce3af7a9d627 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Fri, 24 Dec 2021 00:15:35 -0500 Subject: [PATCH 38/47] stop handling tuples and arrays --- clippy_lints/src/single_field_patterns.rs | 74 +---------- tests/ui/single_field_patterns.rs | 128 ++----------------- tests/ui/single_field_patterns.stderr | 145 +--------------------- 3 files changed, 16 insertions(+), 331 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index a4758f033e99..9204c52ed87f 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -54,7 +54,6 @@ declare_lint_pass!(SingleFieldPatterns => [SINGLE_FIELD_PATTERNS]); #[derive(Debug, Clone, Copy)] enum SingleField { Id { id: Ident, pattern: Span }, - Index { index: usize, pattern: Span }, Unused, // The name "SingleField" is a lie but idk what's better. "AtMostOneField"? } @@ -62,38 +61,21 @@ impl PartialEq for SingleField { fn eq(&self, other: &Self) -> bool { match (self, other) { (SingleField::Id { id: id1, .. }, SingleField::Id { id: id2, .. }) => id1 == id2, - (SingleField::Index { index: index1, .. }, SingleField::Index { index: index2, .. }) => index1 == index2, (SingleField::Unused, SingleField::Unused) => true, _ => false, } } } -trait IntoSingleField { - fn into_sf(self, span: Span) -> SingleField; -} - -impl IntoSingleField for Ident { - fn into_sf(self, pattern: Span) -> SingleField { - SingleField::Id { id: self, pattern } - } -} - -impl IntoSingleField for usize { - fn into_sf(self, pattern: Span) -> SingleField { - SingleField::Index { index: self, pattern } - } -} - -fn get_sf<'a, ID: IntoSingleField>(mut iter: impl Iterator)>) -> Option { +fn get_sf<'a>(mut iter: impl Iterator)>) -> Option { let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); match one { - Some((index, pat)) => { + Some((id, pat)) => { if pat.span.from_expansion() { return None; } if iter.all(|(_, other)| matches!(other.kind, PatKind::Wild)) { - Some(index.into_sf(pat.span)) + Some(SingleField::Id { id, pattern: pat.span }) } else { None } @@ -102,46 +84,13 @@ fn get_sf<'a, ID: IntoSingleField>(mut iter: impl Iterator], leap: Option) -> Option { - get_sf(pats.iter().enumerate()).and_then(|field| { - if let SingleField::Index { index, .. } = field { - // exclude (.., x) type patterns - if let Some(leap_index) = leap { - if leap_index <= index { - return None; - } - } - } - Some(field) - }) -} - fn struct_sf(pat: &PatKind<'_>) -> Option { match *pat { PatKind::Struct(_, pats, _) => get_sf(pats.iter().map(|field| (field.ident, field.pat))), - PatKind::TupleStruct(_, pats, leap) => inner_tuple_sf(pats, leap), _ => None, } } -fn tuple_sf(pat: &PatKind<'_>) -> Option { - if let PatKind::Tuple(pats, leap) = *pat { - inner_tuple_sf(pats, leap) - } else { - None - } -} - -fn slice_sf(pat: &PatKind<'_>) -> Option { - if let PatKind::Slice(before, dots, after) = pat { - // exclude [.., x] type patterns - if dots.is_none() || after.is_empty() { - return get_sf(before.iter().enumerate()); - } - } - None -} - /// This handles recursive patterns and flattens them out lazily /// e.g. 1 | (2 | 9) | 3..5 struct FlatPatterns<'hir, I> @@ -208,7 +157,7 @@ fn find_sf_lint<'hir>( SingleField::Unused => { spans.push((target, String::from("_"))); }, - SingleField::Id { pattern, .. } | SingleField::Index { pattern, .. } => { + SingleField::Id { pattern, .. } => { if let Some(str) = snippet_opt(cx, pattern) { spans.push((target, str)); } else { @@ -265,31 +214,18 @@ fn lint_sf<'hir>( return; }; match cx.typeck_results().expr_ty(scrutinee).kind() { - ty::TyKind::Adt(def @ ty::AdtDef { .. }, ..) if def.is_struct() => { + ty::TyKind::Adt(def, ..) if def.is_struct() => { if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &struct_sf) { spans.push(( scrutinee.span, match field { SingleField::Id { id, .. } => format!("{}.{}", scrutinee_name, id.as_str()), - SingleField::Index { index, .. } => format!("{}.{}", scrutinee_name, index), SingleField::Unused => return, }, )); apply_lint_sf(cx, overall_span, spans); } }, - ty::TyKind::Array(..) => { - if let Some((SingleField::Index { index, .. }, mut spans)) = find_sf_lint(cx, patterns, &slice_sf) { - spans.push((scrutinee.span, format!("{}[{}]", scrutinee_name, index))); - apply_lint_sf(cx, overall_span, spans); - } - }, - ty::TyKind::Tuple(..) => { - if let Some((SingleField::Index { index, .. }, mut spans)) = find_sf_lint(cx, patterns, &tuple_sf) { - spans.push((scrutinee.span, format!("{}.{}", scrutinee_name, index))); - apply_lint_sf(cx, overall_span, spans); - } - }, _ => (), }; } diff --git a/tests/ui/single_field_patterns.rs b/tests/ui/single_field_patterns.rs index 85577e4e04e0..be3a30f09650 100644 --- a/tests/ui/single_field_patterns.rs +++ b/tests/ui/single_field_patterns.rs @@ -36,61 +36,27 @@ fn lint_ref(struct1: &&Struct) { let Struct { field1, .. } = **struct1; } -struct Tuple(Option, Option); - -fn lint_tuple_struct(tuple: Tuple) { - if let Tuple(Some(x), _) = tuple {} - if let Tuple(_, Some(y)) = tuple {} - match tuple { - Tuple(Some(1), ..) => {}, - Tuple(Some(2), ..) => {}, - Tuple(a, ..) => {}, - } - match tuple { - Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, - Tuple(a, ..) => {}, - } -} - -fn lint_tuple(tuple: (Option, Option)) { - if let (Some(z), _) = tuple {} - if let (_, Some(n)) = tuple {} - match tuple { - (Some(1), ..) => {}, - (Some(2), ..) => {}, - (a, ..) => {}, - } - match tuple { - (Some(1) | Some(42) | Some(6082), ..) => {}, - (a, ..) => {}, - } -} - -fn lint_array(array: [i32; 3]) { - match array { - [1 | 2, ..] => {}, - [x @ 3, ..] => {}, - [r @ 20..=65, ..] => {}, - [e, ..] => {}, - } - if let [5, ..] = array {} -} - macro_rules! mac { () => { - (1, 2, 3) + Struct { + field1: Some(1), + field2: Some(2), + } }; } macro_rules! pat { ($id:ident) => { - (_, $id, _) + Struct { field1: $id, field2: _ } }; } fn ok_macro() { - let (_, a, _) = mac!(); - let pat!(a) = (1, 2, 3); + let Struct { .. } = mac!(); + let pat!(a) = Struct { + field1: None, + field2: None, + }; let (pat!(a), _) = (mac!(), mac!()); } @@ -120,78 +86,4 @@ fn ok_struct(struct1: Struct) { let s @ Struct { field1, .. } = struct1; } -fn ok_tuple_struct(tuple: Tuple) { - if let Tuple(Some(1), two) = tuple {} - if let Tuple(one, Some(1)) = tuple {} - match tuple { - Tuple(Some(1), _) => {}, - Tuple(_, Some(1)) => {}, - _ => {}, - } - match tuple { - Tuple(Some(1), ..) => {}, - Tuple(.., Some(1)) => {}, - _ => {}, - } - match tuple { - Tuple(.., Some(1)) => {}, - Tuple(.., Some(2)) => {}, - Tuple(.., None) => {}, - _ => {}, - } - let t @ Tuple(_, two) = tuple; -} - -fn ok_tuple(tuple: (Option, Option)) { - if let (None, two) = tuple {} - if let (one, Some(1)) = tuple {} - match tuple { - (Some(1), _) => {}, - (_, Some(1)) => {}, - _ => {}, - } - match tuple { - (.., Some(1)) => {}, - (.., Some(2)) => {}, - (.., None) => {}, - _ => {}, - } - match tuple { - (Some(1), ..) => {}, - (.., Some(1)) => {}, - _ => {}, - } - let t @ (one, two) = tuple; -} - -fn ok_array(array: [i32; 555]) { - if let [.., 209, _] = array {} -} - -fn ok_slice(slice: &[i32]) { - // slices may panic if indexed, but will never panic - // in a pattern since they're forced to check if they're empty - match slice { - [.., x] => {}, - [] => {}, - } - if let [x, ..] = slice {} -} - -enum Enum { - Enum(Option, Option), - OtherEnum, -} - -fn ok_enum(enum1: Enum) { - // Should never touch enums for this lint - // since there's no way to access a field directly - if let Enum::Enum(one, _) = enum1 {} - match enum1 { - Enum::Enum(one, ..) => {}, - Enum::Enum(_, _) => {}, - Enum::OtherEnum => {}, - } -} - fn main() {} diff --git a/tests/ui/single_field_patterns.stderr b/tests/ui/single_field_patterns.stderr index 6d07f590bc78..133dc140606a 100644 --- a/tests/ui/single_field_patterns.stderr +++ b/tests/ui/single_field_patterns.stderr @@ -115,148 +115,5 @@ help: try this LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:42:5 - | -LL | if let Tuple(Some(x), _) = tuple {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try this - | -LL | if let Some(x) = tuple.0 {} - | ~~~~~~~ ~~~~~~~ - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:43:5 - | -LL | if let Tuple(_, Some(y)) = tuple {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try this - | -LL | if let Some(y) = tuple.1 {} - | ~~~~~~~ ~~~~~~~ - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:44:5 - | -LL | / match tuple { -LL | | Tuple(Some(1), ..) => {}, -LL | | Tuple(Some(2), ..) => {}, -LL | | Tuple(a, ..) => {}, -LL | | } - | |_____^ - | -help: try this - | -LL ~ match tuple.0 { -LL ~ Some(1) => {}, -LL ~ Some(2) => {}, -LL ~ a => {}, - | - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:49:5 - | -LL | / match tuple { -LL | | Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, -LL | | Tuple(a, ..) => {}, -LL | | } - | |_____^ - | -help: try this - | -LL ~ match tuple.0 { -LL ~ Some(1) | Some(42) | Some(6082) => {}, -LL ~ a => {}, - | - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:56:5 - | -LL | if let (Some(z), _) = tuple {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try this - | -LL | if let Some(z) = tuple.0 {} - | ~~~~~~~ ~~~~~~~ - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:57:5 - | -LL | if let (_, Some(n)) = tuple {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try this - | -LL | if let Some(n) = tuple.1 {} - | ~~~~~~~ ~~~~~~~ - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:58:5 - | -LL | / match tuple { -LL | | (Some(1), ..) => {}, -LL | | (Some(2), ..) => {}, -LL | | (a, ..) => {}, -LL | | } - | |_____^ - | -help: try this - | -LL ~ match tuple.0 { -LL ~ Some(1) => {}, -LL ~ Some(2) => {}, -LL ~ a => {}, - | - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:63:5 - | -LL | / match tuple { -LL | | (Some(1) | Some(42) | Some(6082), ..) => {}, -LL | | (a, ..) => {}, -LL | | } - | |_____^ - | -help: try this - | -LL ~ match tuple.0 { -LL ~ Some(1) | Some(42) | Some(6082) => {}, -LL ~ a => {}, - | - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:70:5 - | -LL | / match array { -LL | | [1 | 2, ..] => {}, -LL | | [x @ 3, ..] => {}, -LL | | [r @ 20..=65, ..] => {}, -LL | | [e, ..] => {}, -LL | | } - | |_____^ - | -help: try this - | -LL ~ match array[0] { -LL ~ 1 | 2 => {}, -LL ~ x @ 3 => {}, -LL ~ r @ 20..=65 => {}, -LL ~ e => {}, - | - -error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:76:5 - | -LL | if let [5, ..] = array {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try this - | -LL | if let 5 = array[0] {} - | ~ ~~~~~~~~ - -error: aborting due to 18 previous errors +error: aborting due to 8 previous errors From 42189afb2370e9444c4c3e3550b7a3ee7d8a2e22 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Fri, 24 Dec 2021 00:18:32 -0500 Subject: [PATCH 39/47] Revert "internal lints" This reverts commit 1ccef1498a362a6a08b380b4a231129bd75dbc6e. --- clippy_lints/src/comparison_chain.rs | 2 +- clippy_lints/src/dereference.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 4 ++-- clippy_lints/src/manual_map.rs | 2 +- clippy_lints/src/manual_strip.rs | 2 +- clippy_lints/src/open_options.rs | 6 +++++- clippy_lints/src/utils/internal_lints/metadata_collector.rs | 6 +++--- clippy_lints/src/write.rs | 4 ++-- 8 files changed, 16 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index a75d0be60d4f..399d11472b09 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain { } // Check that there exists at least one explicit else condition - let conds = if_sequence(expr).0; + let (conds, _) = if_sequence(expr); if conds.len() < 2 { return; } diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 7ca44d0d5f06..fa2b348591be 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -508,7 +508,7 @@ fn report(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: Stat let mut app = Applicability::MachineApplicable; let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); let ty = cx.typeck_results().expr_ty(expr); - let ref_count = peel_mid_ty_refs(ty).1; + let (_, ref_count) = peel_mid_ty_refs(ty); let deref_str = if ty_changed_count >= ref_count && ref_count != 0 { // a deref call changing &T -> &U requires two deref operators the first time // this occurs. One to remove the reference, a second to call the deref impl. diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 14b8787ba8fb..9ead4bb27a58 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { let const_range = to_const_range(cx, range, size); - if let Some(start) = const_range.0 { + if let (Some(start), _) = const_range { if start > size { span_lint( cx, @@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { } } - if let Some(end) = const_range.1 { + if let (_, Some(end)) = const_range { if end > size { span_lint( cx, diff --git a/clippy_lints/src/manual_map.rs b/clippy_lints/src/manual_map.rs index a0d2e6d92772..34a70ca76c6a 100644 --- a/clippy_lints/src/manual_map.rs +++ b/clippy_lints/src/manual_map.rs @@ -150,7 +150,7 @@ impl LateLintPass<'_> for ManualMap { // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; - let scrutinee_str = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app).0; + let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX { format!("({})", scrutinee_str) diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 7ddaf19d35a4..f8e28f1671f0 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -146,7 +146,7 @@ fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx E // Returns the length of the `expr` if it's a constant string or char. fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { - let value = constant(cx, cx.typeck_results(), expr)?.0; + let (value, _) = constant(cx, cx.typeck_results(), expr)?; match value { Constant::Str(value) => Some(value.len() as u128), Constant::Char(value) => Some(value.len_utf8() as u128), diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 3ec75abaaf21..2477c7d4ff97 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -67,7 +67,11 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { let argument_option = match arguments[1].kind { ExprKind::Lit(ref span) => { - if let LitKind::Bool(lit) = span.node { + if let Spanned { + node: LitKind::Bool(lit), + .. + } = *span + { if lit { Argument::True } else { Argument::False } } else { // The function is called with a literal which is not a boolean literal. diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index d66ec42c25da..7707eebd6223 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -676,7 +676,7 @@ fn extract_emission_info<'hir>( let mut multi_part = false; for arg in args { - let arg_ty = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg)).0; + let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg)); if match_type(cx, arg_ty, &paths::LINT) { // If we found the lint arg, extract the lint name @@ -809,7 +809,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { } fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - let expr_ty = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)).0; + let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); if_chain! { if match_type(self.cx, expr_ty, &paths::APPLICABILITY); @@ -899,7 +899,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> { } }, ExprKind::MethodCall(path, _path_span, arg, _arg_span) => { - let self_ty = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&arg[0])).0; + let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&arg[0])); if match_type(self.cx, self_ty, &paths::DIAGNOSTIC_BUILDER) { let called_method = path.ident.name.as_str().to_string(); for (method_name, is_multi_part) in &SUGGESTION_DIAGNOSTIC_BUILDER_METHODS { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 8fb68addc083..5bf0cffdbad1 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -624,7 +624,7 @@ impl Write { } fn lint_println_empty_string(&self, cx: &EarlyContext<'_>, mac: &MacCall) { - if let Some(fmt_str) = self.check_tts(cx, mac.args.inner_tokens(), false).0 { + if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) { if fmt_str.symbol == kw::Empty { let name = mac.path.segments[0].ident.name; span_lint_and_sugg( @@ -641,7 +641,7 @@ impl Write { } fn lint_print_with_newline(&self, cx: &EarlyContext<'_>, mac: &MacCall) { - if let Some(fmt_str) = self.check_tts(cx, mac.args.inner_tokens(), false).0 { + if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) { if check_newlines(&fmt_str) { let name = mac.path.segments[0].ident.name; let suggested = format!("{}ln", name); From a0c3cc99f5467e030d027d52fc2524172a4f104f Mon Sep 17 00:00:00 2001 From: hahohihu Date: Fri, 24 Dec 2021 00:19:44 -0500 Subject: [PATCH 40/47] Revert "allow lint in other tests" This reverts commit 3aa0d1782f877b1436ed5608cce5921d4cba56ad. --- tests/ui/author/struct.rs | 2 +- tests/ui/collapsible_match2.rs | 3 +- tests/ui/collapsible_match2.stderr | 20 ++--- tests/ui/eta.fixed | 3 +- tests/ui/eta.rs | 3 +- tests/ui/eta.stderr | 42 +++++----- tests/ui/infallible_destructuring_match.fixed | 2 +- tests/ui/infallible_destructuring_match.rs | 2 +- tests/ui/needless_borrow_pat.rs | 2 +- tests/ui/needless_pass_by_value.rs | 3 +- tests/ui/needless_pass_by_value.stderr | 52 ++++++------ tests/ui/shadow.rs | 1 - tests/ui/shadow.stderr | 84 +++++++++---------- tests/ui/toplevel_ref_arg.fixed | 1 - tests/ui/toplevel_ref_arg.rs | 1 - tests/ui/toplevel_ref_arg.stderr | 12 +-- tests/ui/unneeded_field_pattern.rs | 1 - tests/ui/unneeded_field_pattern.stderr | 4 +- tests/ui/unneeded_wildcard_pattern.fixed | 1 - tests/ui/unneeded_wildcard_pattern.rs | 1 - tests/ui/unneeded_wildcard_pattern.stderr | 28 +++---- tests/ui/unnested_or_patterns.fixed | 7 +- tests/ui/unnested_or_patterns.rs | 7 +- tests/ui/unnested_or_patterns.stderr | 32 +++---- tests/ui/unnested_or_patterns2.fixed | 2 +- tests/ui/unnested_or_patterns2.rs | 2 +- tests/ui/while_let_on_iterator.fixed | 3 +- tests/ui/while_let_on_iterator.rs | 3 +- tests/ui/while_let_on_iterator.stderr | 42 +++++----- 29 files changed, 172 insertions(+), 194 deletions(-) diff --git a/tests/ui/author/struct.rs b/tests/ui/author/struct.rs index dbe3cfcf37e6..5fdf3433a370 100644 --- a/tests/ui/author/struct.rs +++ b/tests/ui/author/struct.rs @@ -1,4 +1,4 @@ -#[allow(clippy::unnecessary_operation, clippy::single_match, clippy::single_field_patterns)] +#[allow(clippy::unnecessary_operation, clippy::single_match)] fn main() { struct Test { field: u32, diff --git a/tests/ui/collapsible_match2.rs b/tests/ui/collapsible_match2.rs index 6731c0f9de6d..542e69484276 100644 --- a/tests/ui/collapsible_match2.rs +++ b/tests/ui/collapsible_match2.rs @@ -3,8 +3,7 @@ clippy::needless_return, clippy::no_effect, clippy::single_match, - clippy::needless_borrow, - clippy::single_field_patterns + clippy::needless_borrow )] fn lint_cases(opt_opt: Option>, res_opt: Result, String>) { diff --git a/tests/ui/collapsible_match2.stderr b/tests/ui/collapsible_match2.stderr index c838b487b66b..46b645aea135 100644 --- a/tests/ui/collapsible_match2.stderr +++ b/tests/ui/collapsible_match2.stderr @@ -1,5 +1,5 @@ error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:14:34 + --> $DIR/collapsible_match2.rs:13:34 | LL | Ok(val) if make() => match val { | __________________________________^ @@ -10,7 +10,7 @@ LL | | }, | = note: `-D clippy::collapsible-match` implied by `-D warnings` help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:14:16 + --> $DIR/collapsible_match2.rs:13:16 | LL | Ok(val) if make() => match val { | ^^^ replace this binding @@ -18,7 +18,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:21:24 + --> $DIR/collapsible_match2.rs:20:24 | LL | Ok(val) => match val { | ________________________^ @@ -28,7 +28,7 @@ LL | | }, | |_____________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:21:16 + --> $DIR/collapsible_match2.rs:20:16 | LL | Ok(val) => match val { | ^^^ replace this binding @@ -36,7 +36,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:35:29 + --> $DIR/collapsible_match2.rs:34:29 | LL | $pat => match $e { | _____________________________^ @@ -49,7 +49,7 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ------------------------------------------------ in this macro invocation | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:47:28 + --> $DIR/collapsible_match2.rs:46:28 | LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ^^^ ^^^^^^^ with this pattern @@ -58,7 +58,7 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:52:20 + --> $DIR/collapsible_match2.rs:51:20 | LL | Some(s) => match *s { | ____________________^ @@ -68,7 +68,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:52:14 + --> $DIR/collapsible_match2.rs:51:14 | LL | Some(s) => match *s { | ^ replace this binding @@ -76,7 +76,7 @@ LL | [n] => foo(n), | ^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> $DIR/collapsible_match2.rs:61:24 + --> $DIR/collapsible_match2.rs:60:24 | LL | Some(ref s) => match &*s { | ________________________^ @@ -86,7 +86,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:61:14 + --> $DIR/collapsible_match2.rs:60:14 | LL | Some(ref s) => match &*s { | ^^^^^ replace this binding diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index 022af70502db..1de79667f55f 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -5,8 +5,7 @@ clippy::no_effect, clippy::redundant_closure_call, clippy::needless_pass_by_value, - clippy::option_map_unit_fn, - clippy::single_field_patterns + clippy::option_map_unit_fn )] #![warn( clippy::redundant_closure, diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 1276e1e61a97..86abd347baa7 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -5,8 +5,7 @@ clippy::no_effect, clippy::redundant_closure_call, clippy::needless_pass_by_value, - clippy::option_map_unit_fn, - clippy::single_field_patterns + clippy::option_map_unit_fn )] #![warn( clippy::redundant_closure, diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 48d7e9e9c962..8092f04c3fc3 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure - --> $DIR/eta.rs:32:27 + --> $DIR/eta.rs:31:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: replace the closure with the function itself: `foo` @@ -7,19 +7,19 @@ LL | let a = Some(1u8).map(|a| foo(a)); = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:36:40 + --> $DIR/eta.rs:35:40 | LL | let _: Option> = true.then(|| vec![]); // special case vec! | ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new` error: redundant closure - --> $DIR/eta.rs:37:35 + --> $DIR/eta.rs:36:35 | LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2` error: this expression borrows a reference (`&u8`) that is immediately dereferenced by the compiler - --> $DIR/eta.rs:38:21 + --> $DIR/eta.rs:37:21 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` @@ -27,25 +27,25 @@ LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted = note: `-D clippy::needless-borrow` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:38:26 + --> $DIR/eta.rs:37:26 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below` error: redundant closure - --> $DIR/eta.rs:44:27 + --> $DIR/eta.rs:43:27 | LL | let e = Some(1u8).map(|a| divergent(a)); | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `divergent` error: redundant closure - --> $DIR/eta.rs:45:27 + --> $DIR/eta.rs:44:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> $DIR/eta.rs:91:51 + --> $DIR/eta.rs:90:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -53,79 +53,79 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:92:51 + --> $DIR/eta.rs:91:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> $DIR/eta.rs:94:42 + --> $DIR/eta.rs:93:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> $DIR/eta.rs:98:29 + --> $DIR/eta.rs:97:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> $DIR/eta.rs:99:27 + --> $DIR/eta.rs:98:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> $DIR/eta.rs:101:65 + --> $DIR/eta.rs:100:65 | LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> $DIR/eta.rs:164:22 + --> $DIR/eta.rs:163:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> $DIR/eta.rs:171:27 + --> $DIR/eta.rs:170:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> $DIR/eta.rs:176:27 + --> $DIR/eta.rs:175:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> $DIR/eta.rs:208:28 + --> $DIR/eta.rs:207:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:209:28 + --> $DIR/eta.rs:208:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:210:28 + --> $DIR/eta.rs:209:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> $DIR/eta.rs:217:21 + --> $DIR/eta.rs:216:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> $DIR/eta.rs:236:21 + --> $DIR/eta.rs:235:21 | LL | map_str_to_path(|s| s.as_ref()); | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::convert::AsRef::as_ref` diff --git a/tests/ui/infallible_destructuring_match.fixed b/tests/ui/infallible_destructuring_match.fixed index 60418e619ba8..b8e40d995531 100644 --- a/tests/ui/infallible_destructuring_match.fixed +++ b/tests/ui/infallible_destructuring_match.fixed @@ -1,7 +1,7 @@ // run-rustfix #![feature(exhaustive_patterns, never_type)] #![allow(dead_code, unreachable_code, unused_variables)] -#![allow(clippy::let_and_return, clippy::single_field_patterns)] +#![allow(clippy::let_and_return)] enum SingleVariantEnum { Variant(i32), diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index be3de028fc5e..106cd438b90e 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,7 +1,7 @@ // run-rustfix #![feature(exhaustive_patterns, never_type)] #![allow(dead_code, unreachable_code, unused_variables)] -#![allow(clippy::let_and_return, clippy::single_field_patterns)] +#![allow(clippy::let_and_return)] enum SingleVariantEnum { Variant(i32), diff --git a/tests/ui/needless_borrow_pat.rs b/tests/ui/needless_borrow_pat.rs index 252ca6e914f4..04b6283da3c3 100644 --- a/tests/ui/needless_borrow_pat.rs +++ b/tests/ui/needless_borrow_pat.rs @@ -1,7 +1,7 @@ // FIXME: run-rustfix waiting on multi-span suggestions #![warn(clippy::needless_borrow)] -#![allow(clippy::needless_borrowed_reference, clippy::single_field_patterns)] +#![allow(clippy::needless_borrowed_reference)] fn f1(_: &str) {} macro_rules! m1 { diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index c94e758a88b1..5a35b100afe0 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -4,8 +4,7 @@ clippy::single_match, clippy::redundant_pattern_matching, clippy::option_option, - clippy::redundant_clone, - clippy::single_field_patterns + clippy::redundant_clone )] use std::borrow::Borrow; diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 2f61ba241c45..d960c86a9f0e 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,5 +1,5 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:18:23 + --> $DIR/needless_pass_by_value.rs:17:23 | LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` @@ -7,55 +7,55 @@ LL | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec $DIR/needless_pass_by_value.rs:32:11 + --> $DIR/needless_pass_by_value.rs:31:11 | LL | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:32:22 + --> $DIR/needless_pass_by_value.rs:31:22 | LL | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:38:71 + --> $DIR/needless_pass_by_value.rs:37:71 | LL | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:50:18 + --> $DIR/needless_pass_by_value.rs:49:18 | LL | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&Option>` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:63:24 + --> $DIR/needless_pass_by_value.rs:62:24 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:63:36 + --> $DIR/needless_pass_by_value.rs:62:36 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:79:49 + --> $DIR/needless_pass_by_value.rs:78:49 | LL | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:81:18 + --> $DIR/needless_pass_by_value.rs:80:18 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:81:29 + --> $DIR/needless_pass_by_value.rs:80:29 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ @@ -70,13 +70,13 @@ LL | let _ = t.to_string(); | ~~~~~~~~~~~~~ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:81:40 + --> $DIR/needless_pass_by_value.rs:80:40 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:81:53 + --> $DIR/needless_pass_by_value.rs:80:53 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ @@ -91,85 +91,85 @@ LL | let _ = v.to_owned(); | ~~~~~~~~~~~~ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:94:12 + --> $DIR/needless_pass_by_value.rs:93:12 | LL | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:95:12 + --> $DIR/needless_pass_by_value.rs:94:12 | LL | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:104:23 + --> $DIR/needless_pass_by_value.rs:103:23 | LL | fn baz(&self, _u: U, _s: Self) {} | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:104:30 + --> $DIR/needless_pass_by_value.rs:103:30 | LL | fn baz(&self, _u: U, _s: Self) {} | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:126:24 + --> $DIR/needless_pass_by_value.rs:125:24 | LL | fn bar_copy(x: u32, y: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as `Copy` - --> $DIR/needless_pass_by_value.rs:124:1 + --> $DIR/needless_pass_by_value.rs:123:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:132:29 + --> $DIR/needless_pass_by_value.rs:131:29 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as `Copy` - --> $DIR/needless_pass_by_value.rs:124:1 + --> $DIR/needless_pass_by_value.rs:123:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:132:45 + --> $DIR/needless_pass_by_value.rs:131:45 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as `Copy` - --> $DIR/needless_pass_by_value.rs:124:1 + --> $DIR/needless_pass_by_value.rs:123:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:132:61 + --> $DIR/needless_pass_by_value.rs:131:61 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: consider marking this type as `Copy` - --> $DIR/needless_pass_by_value.rs:124:1 + --> $DIR/needless_pass_by_value.rs:123:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:144:40 + --> $DIR/needless_pass_by_value.rs:143:40 | LL | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {} | ^ help: consider taking a reference instead: `&S` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:149:20 + --> $DIR/needless_pass_by_value.rs:148:20 | LL | fn more_fun(_item: impl Club<'static, i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index f030b5a850ee..06f6949b66f5 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,5 +1,4 @@ #![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] -#![allow(clippy::single_field_patterns)] fn shadow_same() { let x = 1; diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index f5923e1ae538..dcc7d4e6b2ff 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,254 +1,254 @@ error: `x` is shadowed by itself in `x` - --> $DIR/shadow.rs:6:9 + --> $DIR/shadow.rs:5:9 | LL | let x = x; | ^ | = note: `-D clippy::shadow-same` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:5:9 + --> $DIR/shadow.rs:4:9 | LL | let x = 1; | ^ error: `mut x` is shadowed by itself in `&x` - --> $DIR/shadow.rs:7:13 + --> $DIR/shadow.rs:6:13 | LL | let mut x = &x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:6:9 + --> $DIR/shadow.rs:5:9 | LL | let x = x; | ^ error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:8:9 + --> $DIR/shadow.rs:7:9 | LL | let x = &mut x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:7:9 + --> $DIR/shadow.rs:6:9 | LL | let mut x = &x; | ^^^^^ error: `x` is shadowed by itself in `*x` - --> $DIR/shadow.rs:9:9 + --> $DIR/shadow.rs:8:9 | LL | let x = *x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:8:9 + --> $DIR/shadow.rs:7:9 | LL | let x = &mut x; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:13:9 | LL | let x = x.0; | ^ | = note: `-D clippy::shadow-reuse` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:13:9 + --> $DIR/shadow.rs:12:9 | LL | let x = ([[0]], ()); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:15:9 + --> $DIR/shadow.rs:14:9 | LL | let x = x[0]; | ^ | note: previous binding is here - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:13:9 | LL | let x = x.0; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:16:10 + --> $DIR/shadow.rs:15:10 | LL | let [x] = x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:15:9 + --> $DIR/shadow.rs:14:9 | LL | let x = x[0]; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:17:9 + --> $DIR/shadow.rs:16:9 | LL | let x = Some(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:16:10 + --> $DIR/shadow.rs:15:10 | LL | let [x] = x; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:18:9 + --> $DIR/shadow.rs:17:9 | LL | let x = foo(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:17:9 + --> $DIR/shadow.rs:16:9 | LL | let x = Some(x); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:19:9 + --> $DIR/shadow.rs:18:9 | LL | let x = || x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:18:9 + --> $DIR/shadow.rs:17:9 | LL | let x = foo(x); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:20:9 + --> $DIR/shadow.rs:19:9 | LL | let x = Some(1).map(|_| x)?; | ^ | note: previous binding is here - --> $DIR/shadow.rs:19:9 + --> $DIR/shadow.rs:18:9 | LL | let x = || x; | ^ error: `y` is shadowed - --> $DIR/shadow.rs:22:9 + --> $DIR/shadow.rs:21:9 | LL | let y = match y { | ^ | note: previous binding is here - --> $DIR/shadow.rs:21:9 + --> $DIR/shadow.rs:20:9 | LL | let y = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:31:9 + --> $DIR/shadow.rs:30:9 | LL | let x = 2; | ^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:30:9 + --> $DIR/shadow.rs:29:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:36:13 + --> $DIR/shadow.rs:35:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:35:10 + --> $DIR/shadow.rs:34:10 | LL | fn f(x: u32) { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:41:14 + --> $DIR/shadow.rs:40:14 | LL | Some(x) => { | ^ | note: previous binding is here - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:42:17 + --> $DIR/shadow.rs:41:17 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:41:14 + --> $DIR/shadow.rs:40:14 | LL | Some(x) => { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:46:17 + --> $DIR/shadow.rs:45:17 | LL | if let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:47:20 + --> $DIR/shadow.rs:46:20 | LL | while let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:48:15 + --> $DIR/shadow.rs:47:15 | LL | let _ = |[x]: [u32; 1]| { | ^ | note: previous binding is here - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:49:13 + --> $DIR/shadow.rs:48:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:48:15 + --> $DIR/shadow.rs:47:15 | LL | let _ = |[x]: [u32; 1]| { | ^ error: `_b` shadows a previous, unrelated binding - --> $DIR/shadow.rs:86:9 + --> $DIR/shadow.rs:85:9 | LL | let _b = _a; | ^^ | note: previous binding is here - --> $DIR/shadow.rs:85:28 + --> $DIR/shadow.rs:84:28 | LL | pub async fn foo2(_a: i32, _b: i64) { | ^^ diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed index 8495a9395eca..b129d95c5602 100644 --- a/tests/ui/toplevel_ref_arg.fixed +++ b/tests/ui/toplevel_ref_arg.fixed @@ -2,7 +2,6 @@ // aux-build:macro_rules.rs #![warn(clippy::toplevel_ref_arg)] -#![allow(clippy::single_field_patterns)] #[macro_use] extern crate macro_rules; diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 831e24f9bb50..73eb4ff7306f 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -2,7 +2,6 @@ // aux-build:macro_rules.rs #![warn(clippy::toplevel_ref_arg)] -#![allow(clippy::single_field_patterns)] #[macro_use] extern crate macro_rules; diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index d1ca6e0cc5fb..9c853020ab01 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -1,5 +1,5 @@ error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:21:9 + --> $DIR/toplevel_ref_arg.rs:20:9 | LL | let ref _x = 1; | ----^^^^^^----- help: try: `let _x = &1;` @@ -7,31 +7,31 @@ LL | let ref _x = 1; = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:23:9 + --> $DIR/toplevel_ref_arg.rs:22:9 | LL | let ref _y: (&_, u8) = (&1, 2); | ----^^^^^^--------------------- help: try: `let _y: &(&_, u8) = &(&1, 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:25:9 + --> $DIR/toplevel_ref_arg.rs:24:9 | LL | let ref _z = 1 + 2; | ----^^^^^^--------- help: try: `let _z = &(1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:27:9 + --> $DIR/toplevel_ref_arg.rs:26:9 | LL | let ref mut _z = 1 + 2; | ----^^^^^^^^^^--------- help: try: `let _z = &mut (1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:32:9 + --> $DIR/toplevel_ref_arg.rs:31:9 | LL | let ref _x = vec![1, 2, 3]; | ----^^^^^^----------------- help: try: `let _x = &vec![1, 2, 3];` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> $DIR/toplevel_ref_arg.rs:12:13 + --> $DIR/toplevel_ref_arg.rs:11:13 | LL | let ref _y = 42; | ----^^^^^^------ help: try: `let _y = &42;` diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index 6dc86fb11166..fa639aa70d61 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,5 +1,4 @@ #![warn(clippy::unneeded_field_pattern)] -#![allow(clippy::single_field_patterns)] #[allow(dead_code, unused)] struct Foo { diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index 5614e82207a8..b8d3c2945322 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,5 +1,5 @@ error: you matched a field with a wildcard pattern, consider using `..` instead - --> $DIR/unneeded_field_pattern.rs:15:15 + --> $DIR/unneeded_field_pattern.rs:14:15 | LL | Foo { a: _, b: 0, .. } => {}, | ^^^^ @@ -8,7 +8,7 @@ LL | Foo { a: _, b: 0, .. } => {}, = help: try with `Foo { b: 0, .. }` error: all the struct fields are matched to a wildcard pattern, consider using `..` - --> $DIR/unneeded_field_pattern.rs:17:9 + --> $DIR/unneeded_field_pattern.rs:16:9 | LL | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unneeded_wildcard_pattern.fixed b/tests/ui/unneeded_wildcard_pattern.fixed index 1d70fe6c6f8b..12c3461c9557 100644 --- a/tests/ui/unneeded_wildcard_pattern.fixed +++ b/tests/ui/unneeded_wildcard_pattern.fixed @@ -1,7 +1,6 @@ // run-rustfix #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] -#![allow(clippy::single_field_patterns)] fn main() { let t = (0, 1, 2, 3); diff --git a/tests/ui/unneeded_wildcard_pattern.rs b/tests/ui/unneeded_wildcard_pattern.rs index c9fe9068bc70..4ac01d5d23b0 100644 --- a/tests/ui/unneeded_wildcard_pattern.rs +++ b/tests/ui/unneeded_wildcard_pattern.rs @@ -1,7 +1,6 @@ // run-rustfix #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] -#![allow(clippy::single_field_patterns)] fn main() { let t = (0, 1, 2, 3); diff --git a/tests/ui/unneeded_wildcard_pattern.stderr b/tests/ui/unneeded_wildcard_pattern.stderr index 8a004b77e941..716d9ecff89a 100644 --- a/tests/ui/unneeded_wildcard_pattern.stderr +++ b/tests/ui/unneeded_wildcard_pattern.stderr @@ -1,5 +1,5 @@ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:9:18 + --> $DIR/unneeded_wildcard_pattern.rs:8:18 | LL | if let (0, .., _) = t {}; | ^^^ help: remove it @@ -11,79 +11,79 @@ LL | #![deny(clippy::unneeded_wildcard_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:10:16 + --> $DIR/unneeded_wildcard_pattern.rs:9:16 | LL | if let (0, _, ..) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:11:13 + --> $DIR/unneeded_wildcard_pattern.rs:10:13 | LL | if let (_, .., 0) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:12:15 + --> $DIR/unneeded_wildcard_pattern.rs:11:15 | LL | if let (.., _, 0) = t {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:13:16 + --> $DIR/unneeded_wildcard_pattern.rs:12:16 | LL | if let (0, _, _, ..) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:14:18 + --> $DIR/unneeded_wildcard_pattern.rs:13:18 | LL | if let (0, .., _, _) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:23:22 + --> $DIR/unneeded_wildcard_pattern.rs:22:22 | LL | if let (0, .., _, _,) = t {}; | ^^^^^^ help: remove them error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:30:19 + --> $DIR/unneeded_wildcard_pattern.rs:29:19 | LL | if let S(0, .., _) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:31:17 + --> $DIR/unneeded_wildcard_pattern.rs:30:17 | LL | if let S(0, _, ..) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:32:14 + --> $DIR/unneeded_wildcard_pattern.rs:31:14 | LL | if let S(_, .., 0) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:33:16 + --> $DIR/unneeded_wildcard_pattern.rs:32:16 | LL | if let S(.., _, 0) = s {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:34:17 + --> $DIR/unneeded_wildcard_pattern.rs:33:17 | LL | if let S(0, _, _, ..) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:35:19 + --> $DIR/unneeded_wildcard_pattern.rs:34:19 | LL | if let S(0, .., _, _) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:44:23 + --> $DIR/unneeded_wildcard_pattern.rs:43:23 | LL | if let S(0, .., _, _,) = s {}; | ^^^^^^ help: remove them diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index f4f2e7f21915..46463a29e9b2 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -2,12 +2,7 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow( - clippy::cognitive_complexity, - clippy::match_ref_pats, - clippy::upper_case_acronyms, - clippy::single_field_patterns -)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index fa1c73c737ab..8ce0738bfc27 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -2,12 +2,7 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow( - clippy::cognitive_complexity, - clippy::match_ref_pats, - clippy::upper_case_acronyms, - clippy::single_field_patterns -)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index a8ad2659c2a8..de424c3fdb8f 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:14:12 + --> $DIR/unnested_or_patterns.rs:9:12 | LL | if let box 0 | box 2 = Box::new(0) {} | ^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let box (0 | 2) = Box::new(0) {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:15:12 + --> $DIR/unnested_or_patterns.rs:10:12 | LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:17:12 + --> $DIR/unnested_or_patterns.rs:12:12 | LL | if let &0 | C0 | &2 = &0 {} | ^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let &(0 | 2) | C0 = &0 {} | ~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:18:12 + --> $DIR/unnested_or_patterns.rs:13:12 | LL | if let &mut 0 | &mut 2 = &mut 0 {} | ^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let &mut (0 | 2) = &mut 0 {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:19:12 + --> $DIR/unnested_or_patterns.rs:14:12 | LL | if let x @ 0 | x @ 2 = 0 {} | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let x @ (0 | 2) = 0 {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:20:12 + --> $DIR/unnested_or_patterns.rs:15:12 | LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let (0, 1 | 2 | 3) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:21:12 + --> $DIR/unnested_or_patterns.rs:16:12 | LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let (1 | 2 | 3, 0) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:22:12 + --> $DIR/unnested_or_patterns.rs:17:12 | LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | if let (x, ..) | (x, 1 | 2) = (0, 1) {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:23:12 + --> $DIR/unnested_or_patterns.rs:18:12 | LL | if let [0] | [1] = [0] {} | ^^^^^^^^^ @@ -99,7 +99,7 @@ LL | if let [0 | 1] = [0] {} | ~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:24:12 + --> $DIR/unnested_or_patterns.rs:19:12 | LL | if let [x, 0] | [x, 1] = [0, 1] {} | ^^^^^^^^^^^^^^^ @@ -110,7 +110,7 @@ LL | if let [x, 0 | 1] = [0, 1] {} | ~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:25:12 + --> $DIR/unnested_or_patterns.rs:20:12 | LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | if let [x, 0 | 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:26:12 + --> $DIR/unnested_or_patterns.rs:21:12 | LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | if let [x, ..] | [x, 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:28:12 + --> $DIR/unnested_or_patterns.rs:23:12 | LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | if let TS(0 | 1, x) = TS(0, 0) {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:29:12 + --> $DIR/unnested_or_patterns.rs:24:12 | LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | if let TS(1 | 2 | 3, 0) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:30:12 + --> $DIR/unnested_or_patterns.rs:25:12 | LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:35:12 + --> $DIR/unnested_or_patterns.rs:30:12 | LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed index 780f5b0a788f..d3539d798157 100644 --- a/tests/ui/unnested_or_patterns2.fixed +++ b/tests/ui/unnested_or_patterns2.fixed @@ -2,7 +2,7 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::single_field_patterns)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs index 47ac80c020e6..9cea5cdea699 100644 --- a/tests/ui/unnested_or_patterns2.rs +++ b/tests/ui/unnested_or_patterns2.rs @@ -2,7 +2,7 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::single_field_patterns)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index ff17010fb9a7..1e74ad2de655 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -6,8 +6,7 @@ unreachable_code, unused_mut, dead_code, - clippy::equatable_if_let, - clippy::single_field_patterns + clippy::equatable_if_let )] fn base() { diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index ddbb17cf9efa..69cb636cee82 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -6,8 +6,7 @@ unreachable_code, unused_mut, dead_code, - clippy::equatable_if_let, - clippy::single_field_patterns + clippy::equatable_if_let )] fn base() { diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index e0b664d16759..1a11ba26eef0 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:15:5 + --> $DIR/while_let_on_iterator.rs:14:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,85 +7,85 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:20:5 + --> $DIR/while_let_on_iterator.rs:19:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:25:5 + --> $DIR/while_let_on_iterator.rs:24:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:101:9 + --> $DIR/while_let_on_iterator.rs:100:9 | LL | while let Some([..]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:108:9 + --> $DIR/while_let_on_iterator.rs:107:9 | LL | while let Some([_x]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:121:9 + --> $DIR/while_let_on_iterator.rs:120:9 | LL | while let Some(x @ [_]) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:141:9 + --> $DIR/while_let_on_iterator.rs:140:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:198:9 + --> $DIR/while_let_on_iterator.rs:197:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:209:5 + --> $DIR/while_let_on_iterator.rs:208:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:211:9 + --> $DIR/while_let_on_iterator.rs:210:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:220:9 + --> $DIR/while_let_on_iterator.rs:219:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:229:9 + --> $DIR/while_let_on_iterator.rs:228:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:246:9 + --> $DIR/while_let_on_iterator.rs:245:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:261:13 + --> $DIR/while_let_on_iterator.rs:260:13 | LL | while let Some(i) = self.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()` error: manual `!RangeInclusive::contains` implementation - --> $DIR/while_let_on_iterator.rs:262:20 + --> $DIR/while_let_on_iterator.rs:261:20 | LL | if i < 3 || i > 7 { | ^^^^^^^^^^^^^^ help: use: `!(3..=7).contains(&i)` @@ -93,37 +93,37 @@ LL | if i < 3 || i > 7 { = note: `-D clippy::manual-range-contains` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:293:13 + --> $DIR/while_let_on_iterator.rs:292:13 | LL | while let Some(i) = self.0.0.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:322:5 + --> $DIR/while_let_on_iterator.rs:321:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:334:9 + --> $DIR/while_let_on_iterator.rs:333:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:348:5 + --> $DIR/while_let_on_iterator.rs:347:5 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:359:5 + --> $DIR/while_let_on_iterator.rs:358:5 | LL | while let Some(x) = it.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:378:5 + --> $DIR/while_let_on_iterator.rs:377:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` From 04bd2e3c298951d8175fc89928471ff644984ea9 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Fri, 24 Dec 2021 00:21:36 -0500 Subject: [PATCH 41/47] Revert "fix lints" This reverts commit 571289c7b680e62a4aa9c401eeb964e40cc5f331. --- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/open_options.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index fdcae4974ef3..2cdd59c56919 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -547,7 +547,7 @@ fn check_doc<'a, Events: Iterator, Range { diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 2477c7d4ff97..2c77100bdcfc 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -5,7 +5,7 @@ use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; +use rustc_span::source_map::{Span, Spanned}; declare_clippy_lint! { /// ### What it does From 7b0e6f193583141ec4bbebae04e9b30cce3f083e Mon Sep 17 00:00:00 2001 From: hahohihu Date: Fri, 24 Dec 2021 00:32:54 -0500 Subject: [PATCH 42/47] fix tests/self-lint --- clippy_lints/src/open_options.rs | 8 ++------ tests/ui/author/struct.rs | 2 +- tests/ui/unneeded_field_pattern.rs | 1 + tests/ui/unneeded_field_pattern.stderr | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 2c77100bdcfc..3ec75abaaf21 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -5,7 +5,7 @@ use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::{Span, Spanned}; +use rustc_span::source_map::Span; declare_clippy_lint! { /// ### What it does @@ -67,11 +67,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 { let argument_option = match arguments[1].kind { ExprKind::Lit(ref span) => { - if let Spanned { - node: LitKind::Bool(lit), - .. - } = *span - { + if let LitKind::Bool(lit) = span.node { if lit { Argument::True } else { Argument::False } } else { // The function is called with a literal which is not a boolean literal. diff --git a/tests/ui/author/struct.rs b/tests/ui/author/struct.rs index 5fdf3433a370..dbe3cfcf37e6 100644 --- a/tests/ui/author/struct.rs +++ b/tests/ui/author/struct.rs @@ -1,4 +1,4 @@ -#[allow(clippy::unnecessary_operation, clippy::single_match)] +#[allow(clippy::unnecessary_operation, clippy::single_match, clippy::single_field_patterns)] fn main() { struct Test { field: u32, diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index fa639aa70d61..6dc86fb11166 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,4 +1,5 @@ #![warn(clippy::unneeded_field_pattern)] +#![allow(clippy::single_field_patterns)] #[allow(dead_code, unused)] struct Foo { diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index b8d3c2945322..5614e82207a8 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,5 +1,5 @@ error: you matched a field with a wildcard pattern, consider using `..` instead - --> $DIR/unneeded_field_pattern.rs:14:15 + --> $DIR/unneeded_field_pattern.rs:15:15 | LL | Foo { a: _, b: 0, .. } => {}, | ^^^^ @@ -8,7 +8,7 @@ LL | Foo { a: _, b: 0, .. } => {}, = help: try with `Foo { b: 0, .. }` error: all the struct fields are matched to a wildcard pattern, consider using `..` - --> $DIR/unneeded_field_pattern.rs:16:9 + --> $DIR/unneeded_field_pattern.rs:17:9 | LL | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ From 735e7f397d57c44d16e17c8ebc97faf7d1ff2401 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Fri, 28 Jan 2022 23:31:22 -0500 Subject: [PATCH 43/47] code review --- clippy_lints/src/single_field_patterns.rs | 49 +++++++++-------------- tests/ui/single_field_patterns.rs | 47 +++++++++++++++++++++- tests/ui/single_field_patterns.stderr | 49 +++++++++++++++++++---- 3 files changed, 104 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 9204c52ed87f..96e213b1a7ca 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -12,11 +12,11 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{symbol::Ident, Span}; -use std::iter::once; +use std::iter; declare_clippy_lint! { /// ### What it does - /// Checks for patterns that only use a single field when they could directly access the field. + /// Checks for patterns that only match a single field of a struct when they could directly access the field. /// /// ### Why is this bad? /// It requires more text and more information than directly accessing the field. @@ -49,8 +49,8 @@ declare_clippy_lint! { } declare_lint_pass!(SingleFieldPatterns => [SINGLE_FIELD_PATTERNS]); -/// This represents 0 or 1 fields being used. Where more may be used, I use Option -/// where None represents the absence of a lint +/// This represents 0 or 1 fields being used. Where more may be used, `Option` is used +/// where `None` represents the absence of a lint #[derive(Debug, Clone, Copy)] enum SingleField { Id { id: Ident, pattern: Span }, @@ -67,7 +67,8 @@ impl PartialEq for SingleField { } } -fn get_sf<'a>(mut iter: impl Iterator)>) -> Option { +impl SingleField { + fn new<'a>(mut iter: impl Iterator)>) -> Option { let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); match one { Some((id, pat)) => { @@ -83,12 +84,6 @@ fn get_sf<'a>(mut iter: impl Iterator)>) -> Option Some(SingleField::Unused), } } - -fn struct_sf(pat: &PatKind<'_>) -> Option { - match *pat { - PatKind::Struct(_, pats, _) => get_sf(pats.iter().map(|field| (field.ident, field.pat))), - _ => None, - } } /// This handles recursive patterns and flattens them out lazily @@ -133,18 +128,14 @@ impl>> Iterator for FlatPatterns<'hir, I> { fn find_sf_lint<'hir>( cx: &LateContext<'_>, - patterns: impl Iterator>, - leaf_sf: &impl Fn(&PatKind<'hir>) -> Option, + patterns: impl Iterator> ) -> Option<(SingleField, Vec<(Span, String)>)> { - let fields = FlatPatterns::new(patterns).map(|p| { - ( - p.span, - if matches!(p.kind, PatKind::Wild) { - Some(SingleField::Unused) - } else { - leaf_sf(&p.kind) - }, - ) + let fields = FlatPatterns::new(patterns).filter_map(|p| { + match p.kind { + PatKind::Wild => Some(SingleField::Unused), + PatKind::Struct(_, pats, _) => SingleField::new(pats.iter().map(|field| (field.ident, field.pat))), + _ => None + }.map(|sf| (p.span, sf)) }); let mut spans = Vec::<(Span, String)>::new(); let mut the_one: Option = None; @@ -152,7 +143,6 @@ fn find_sf_lint<'hir>( if target.from_expansion() { return None; } - if let Some(sf) = sf { match sf { SingleField::Unused => { spans.push((target, String::from("_"))); @@ -171,9 +161,6 @@ fn find_sf_lint<'hir>( the_one = Some(sf); } }, - } - } else { - return None; } } the_one.map(|one| (one, spans)) @@ -214,8 +201,8 @@ fn lint_sf<'hir>( return; }; match cx.typeck_results().expr_ty(scrutinee).kind() { - ty::TyKind::Adt(def, ..) if def.is_struct() => { - if let Some((field, mut spans)) = find_sf_lint(cx, patterns, &struct_sf) { + ty::Adt(def, ..) if def.is_struct() => { + if let Some((field, mut spans)) = find_sf_lint(cx, patterns) { spans.push(( scrutinee.span, match field { @@ -239,10 +226,10 @@ impl LateLintPass<'_> for SingleFieldPatterns { Some(IfLetOrMatch::Match(scrutinee, arms, MatchSource::Normal)) => { lint_sf(cx, expr.span, scrutinee, arms.iter().map(|arm| arm.pat)); }, - Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => lint_sf(cx, expr.span, scrutinee, once(pat)), + Some(IfLetOrMatch::IfLet(scrutinee, pat, ..)) => lint_sf(cx, expr.span, scrutinee, iter::once(pat)), _ => { if let Some(WhileLet { let_pat, let_expr, .. }) = WhileLet::hir(expr) { - lint_sf(cx, expr.span, let_expr, once(let_pat)); + lint_sf(cx, expr.span, let_expr, iter::once(let_pat)); } }, }; @@ -258,7 +245,7 @@ impl LateLintPass<'_> for SingleFieldPatterns { .. }) = stmt.kind { - lint_sf(cx, stmt.span, scrutinee, once(*pat)); + lint_sf(cx, stmt.span, scrutinee, iter::once(*pat)); } } } diff --git a/tests/ui/single_field_patterns.rs b/tests/ui/single_field_patterns.rs index be3a30f09650..06594593d711 100644 --- a/tests/ui/single_field_patterns.rs +++ b/tests/ui/single_field_patterns.rs @@ -7,6 +7,7 @@ struct Struct { fn lint_struct(struct1: Struct) { let Struct { field1, .. } = struct1; let Struct { field1, field2: _ } = struct1; + if let Struct { field1: None, .. } | Struct { field1: Some(1), .. } = struct1 {} match struct1 { Struct { field1: Some(n), .. } if n >= 50 => {}, Struct { field1: None, .. } => {}, @@ -14,7 +15,7 @@ fn lint_struct(struct1: Struct) { } match struct1 { Struct { field1: Some(n), .. } if n >= 50 => {}, - Struct { .. } => {}, + Struct { .. } | Struct { field1: None, .. } => {}, _ => {}, } match struct1 { @@ -31,9 +32,11 @@ fn lint_struct(struct1: Struct) { while let Struct { field1: Some(5), .. } = struct1 {} } -fn lint_ref(struct1: &&Struct) { +fn lint_ref(struct1: &mut &mut Struct) { // this should suggest struct1.field1, NOT **struct1.field1 let Struct { field1, .. } = **struct1; + let Struct { ref field1, .. } = **struct1; + let Struct { ref mut field1, .. } = **struct1; } macro_rules! mac { @@ -86,4 +89,44 @@ fn ok_struct(struct1: Struct) { let s @ Struct { field1, .. } = struct1; } +struct Tuple(Option, Option); + +fn ok_tuple_struct(tuple: Tuple) { + if let Tuple(Some(x), _) = tuple {} + if let Tuple(_, Some(y)) = tuple {} + match tuple { + Tuple(Some(1), ..) => {}, + Tuple(Some(2), ..) => {}, + Tuple(a, ..) => {}, + } + match tuple { + Tuple(Some(1) | Some(42) | Some(6082), ..) => {}, + Tuple(a, ..) => {}, + } +} + +fn ok_tuple(tuple: (Option, Option)) { + if let (Some(z), _) = tuple {} + if let (_, Some(n)) = tuple {} + match tuple { + (Some(1), ..) => {}, + (Some(2), ..) => {}, + (a, ..) => {}, + } + match tuple { + (Some(1) | Some(42) | Some(6082), ..) => {}, + (a, ..) => {}, + } +} + +fn ok_array(array: [i32; 3]) { + match array { + [1 | 2, ..] => {}, + [x @ 3, ..] => {}, + [r @ 20..=65, ..] => {}, + [e, ..] => {}, + } + if let [5, ..] = array {} +} + fn main() {} diff --git a/tests/ui/single_field_patterns.stderr b/tests/ui/single_field_patterns.stderr index 133dc140606a..ca9a4da38430 100644 --- a/tests/ui/single_field_patterns.stderr +++ b/tests/ui/single_field_patterns.stderr @@ -24,6 +24,17 @@ LL | let field1 = struct1.field1; error: this single-variant pattern only matches one field --> $DIR/single_field_patterns.rs:10:5 | +LL | if let Struct { field1: None, .. } | Struct { field1: Some(1), .. } = struct1 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | if let None | Some(1) = struct1.field1 {} + | ~~~~ ~~~~~~~ ~~~~~~~~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_patterns.rs:11:5 + | LL | / match struct1 { LL | | Struct { field1: Some(n), .. } if n >= 50 => {}, LL | | Struct { field1: None, .. } => {}, @@ -40,11 +51,11 @@ LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:15:5 + --> $DIR/single_field_patterns.rs:16:5 | LL | / match struct1 { LL | | Struct { field1: Some(n), .. } if n >= 50 => {}, -LL | | Struct { .. } => {}, +LL | | Struct { .. } | Struct { field1: None, .. } => {}, LL | | _ => {}, LL | | } | |_____^ @@ -53,12 +64,12 @@ help: try this | LL ~ match struct1.field1 { LL ~ Some(n) if n >= 50 => {}, -LL ~ _ => {}, +LL ~ _ | None => {}, LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:20:5 + --> $DIR/single_field_patterns.rs:21:5 | LL | / match struct1 { LL | | Struct { field1: Some(1), .. } => {}, @@ -78,7 +89,7 @@ LL ~ _ => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:26:5 + --> $DIR/single_field_patterns.rs:27:5 | LL | / match struct1 { LL | | Struct { @@ -94,7 +105,7 @@ LL ~ Some(_) | None => {}, | error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:31:5 + --> $DIR/single_field_patterns.rs:32:5 | LL | while let Struct { field1: Some(5), .. } = struct1 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +116,7 @@ LL | while let Some(5) = struct1.field1 {} | ~~~~~~~ ~~~~~~~~~~~~~~ error: this single-variant pattern only matches one field - --> $DIR/single_field_patterns.rs:36:5 + --> $DIR/single_field_patterns.rs:37:5 | LL | let Struct { field1, .. } = **struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -115,5 +126,27 @@ help: try this LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ -error: aborting due to 8 previous errors +error: this single-variant pattern only matches one field + --> $DIR/single_field_patterns.rs:38:5 + | +LL | let Struct { ref field1, .. } = **struct1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | let ref field1 = struct1.field1; + | ~~~~~~~~~~ ~~~~~~~~~~~~~~ + +error: this single-variant pattern only matches one field + --> $DIR/single_field_patterns.rs:39:5 + | +LL | let Struct { ref mut field1, .. } = **struct1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try this + | +LL | let ref mut field1 = struct1.field1; + | ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ + +error: aborting due to 11 previous errors From 66414f0905b179c9cb110ed33c60740462588163 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 29 Jan 2022 00:04:58 -0500 Subject: [PATCH 44/47] whoops I shouldn't have pushed to master --- clippy_lints/src/single_field_patterns.rs | 49 +++++++++++++---------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index 96e213b1a7ca..edd3cda1c3de 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -69,22 +69,22 @@ impl PartialEq for SingleField { impl SingleField { fn new<'a>(mut iter: impl Iterator)>) -> Option { - let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); - match one { - Some((id, pat)) => { - if pat.span.from_expansion() { - return None; - } - if iter.all(|(_, other)| matches!(other.kind, PatKind::Wild)) { - Some(SingleField::Id { id, pattern: pat.span }) - } else { - None - } - }, - None => Some(SingleField::Unused), + let one = iter.by_ref().find(|(_, pat)| !matches!(pat.kind, PatKind::Wild)); + match one { + Some((id, pat)) => { + if pat.span.from_expansion() { + return None; + } + if iter.all(|(_, other)| matches!(other.kind, PatKind::Wild)) { + Some(SingleField::Id { id, pattern: pat.span }) + } else { + None + } + }, + None => Some(SingleField::Unused), + } } } -} /// This handles recursive patterns and flattens them out lazily /// e.g. 1 | (2 | 9) | 3..5 @@ -128,14 +128,17 @@ impl>> Iterator for FlatPatterns<'hir, I> { fn find_sf_lint<'hir>( cx: &LateContext<'_>, - patterns: impl Iterator> + patterns: impl Iterator>, ) -> Option<(SingleField, Vec<(Span, String)>)> { - let fields = FlatPatterns::new(patterns).filter_map(|p| { - match p.kind { - PatKind::Wild => Some(SingleField::Unused), - PatKind::Struct(_, pats, _) => SingleField::new(pats.iter().map(|field| (field.ident, field.pat))), - _ => None - }.map(|sf| (p.span, sf)) + let fields = FlatPatterns::new(patterns).map(|p| { + ( + p.span, + match p.kind { + PatKind::Wild => Some(SingleField::Unused), + PatKind::Struct(_, pats, _) => SingleField::new(pats.iter().map(|field| (field.ident, field.pat))), + _ => None, + }, + ) }); let mut spans = Vec::<(Span, String)>::new(); let mut the_one: Option = None; @@ -143,6 +146,7 @@ fn find_sf_lint<'hir>( if target.from_expansion() { return None; } + if let Some(sf) = sf { match sf { SingleField::Unused => { spans.push((target, String::from("_"))); @@ -161,6 +165,9 @@ fn find_sf_lint<'hir>( the_one = Some(sf); } }, + } + } else { + return None; } } the_one.map(|one| (one, spans)) From 04512e9aa314635172dd3ad681a78c312a024fa8 Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 29 Jan 2022 00:15:56 -0500 Subject: [PATCH 45/47] change diagnostic --- clippy_lints/src/single_field_patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index edd3cda1c3de..af94f4d49ebb 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -180,7 +180,7 @@ fn apply_lint_sf(cx: &LateContext<'_>, span: Span, sugg: impl IntoIterator Date: Sat, 29 Jan 2022 00:20:35 -0500 Subject: [PATCH 46/47] bless --- tests/ui/single_field_patterns.stderr | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/ui/single_field_patterns.stderr b/tests/ui/single_field_patterns.stderr index ca9a4da38430..5664055e8899 100644 --- a/tests/ui/single_field_patterns.stderr +++ b/tests/ui/single_field_patterns.stderr @@ -5,7 +5,7 @@ LL | let Struct { field1, .. } = struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::single-field-patterns` implied by `-D warnings` -help: try this +help: try accessing this field directly | LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ @@ -16,7 +16,7 @@ error: this single-variant pattern only matches one field LL | let Struct { field1, field2: _ } = struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try accessing this field directly | LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ @@ -27,7 +27,7 @@ error: this single-variant pattern only matches one field LL | if let Struct { field1: None, .. } | Struct { field1: Some(1), .. } = struct1 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try accessing this field directly | LL | if let None | Some(1) = struct1.field1 {} | ~~~~ ~~~~~~~ ~~~~~~~~~~~~~~ @@ -42,7 +42,7 @@ LL | | _ => {}, LL | | } | |_____^ | -help: try this +help: try accessing this field directly | LL ~ match struct1.field1 { LL ~ Some(n) if n >= 50 => {}, @@ -60,7 +60,7 @@ LL | | _ => {}, LL | | } | |_____^ | -help: try this +help: try accessing this field directly | LL ~ match struct1.field1 { LL ~ Some(n) if n >= 50 => {}, @@ -79,7 +79,7 @@ LL | | _ => {}, LL | | } | |_____^ | -help: try this +help: try accessing this field directly | LL ~ match struct1.field1 { LL ~ Some(1) => {}, @@ -98,7 +98,7 @@ LL | | } => {}, LL | | } | |_____^ | -help: try this +help: try accessing this field directly | LL ~ match struct1.field1 { LL ~ Some(_) | None => {}, @@ -110,7 +110,7 @@ error: this single-variant pattern only matches one field LL | while let Struct { field1: Some(5), .. } = struct1 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try accessing this field directly | LL | while let Some(5) = struct1.field1 {} | ~~~~~~~ ~~~~~~~~~~~~~~ @@ -121,7 +121,7 @@ error: this single-variant pattern only matches one field LL | let Struct { field1, .. } = **struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try accessing this field directly | LL | let field1 = struct1.field1; | ~~~~~~ ~~~~~~~~~~~~~~ @@ -132,7 +132,7 @@ error: this single-variant pattern only matches one field LL | let Struct { ref field1, .. } = **struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try accessing this field directly | LL | let ref field1 = struct1.field1; | ~~~~~~~~~~ ~~~~~~~~~~~~~~ @@ -143,7 +143,7 @@ error: this single-variant pattern only matches one field LL | let Struct { ref mut field1, .. } = **struct1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try this +help: try accessing this field directly | LL | let ref mut field1 = struct1.field1; | ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ From d9a2e722c7438fcb4d73a0f880d1cc416c46f45b Mon Sep 17 00:00:00 2001 From: hahohihu Date: Sat, 29 Jan 2022 00:26:20 -0500 Subject: [PATCH 47/47] cargo dev fmt --- clippy_lints/src/single_field_patterns.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/single_field_patterns.rs b/clippy_lints/src/single_field_patterns.rs index af94f4d49ebb..29a455b703a9 100644 --- a/clippy_lints/src/single_field_patterns.rs +++ b/clippy_lints/src/single_field_patterns.rs @@ -180,7 +180,12 @@ fn apply_lint_sf(cx: &LateContext<'_>, span: Span, sugg: impl IntoIterator