From b247594a39cb8e2c3d8d193860eac0eb1c63e1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Thu, 28 Jul 2022 22:54:23 +0200 Subject: [PATCH] Prevent some false positives --- clippy_lints/src/methods/iter_once_empty.rs | 23 ++++++++++++++++++--- clippy_lints/src/types/mod.rs | 1 - clippy_utils/src/lib.rs | 1 - tests/ui/iter_empty.fixed | 8 +++++++ tests/ui/iter_empty.rs | 8 +++++++ tests/ui/iter_once.fixed | 8 +++++++ tests/ui/iter_once.rs | 8 +++++++ 7 files changed, 52 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/iter_once_empty.rs b/clippy_lints/src/methods/iter_once_empty.rs index 82fafb8a45e..96b1484528c 100644 --- a/clippy_lints/src/methods/iter_once_empty.rs +++ b/clippy_lints/src/methods/iter_once_empty.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_lang_ctor; -use clippy_utils::is_no_std_crate; use clippy_utils::source::snippet; +use clippy_utils::{get_expr_use_or_unification_node, is_lang_ctor, is_no_std_crate}; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::LateContext; use super::{ITER_EMPTY, ITER_ONCE}; @@ -56,6 +55,24 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: _ => return, }; + let is_unified = match get_expr_use_or_unification_node(cx.tcx, expr) { + Some((Node::Expr(parent), child_id)) => match parent.kind { + ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id == child_id => false, + ExprKind::If(_, _, _) + | ExprKind::Match(_, _, _) + | ExprKind::Closure(_) + | ExprKind::Ret(_) + | ExprKind::Break(_, _) => true, + _ => false, + }, + Some((Node::Stmt(_) | Node::Local(_), _)) => false, + _ => true, + }; + + if is_unified { + return; + } + if let Some(i) = item { let sugg = format!( "{}::iter::once({}{})", diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index f3ba096237f..353a6f6b899 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -490,7 +490,6 @@ impl Types { } } } - #[allow(clippy::iter_empty)] match *qpath { QPath::Resolved(Some(ty), p) => { context.is_nested_call = true; diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 9c58978a070..dcfc03475b4 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -484,7 +484,6 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res { } fn find_primitive<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator + 'tcx { let single = |ty| tcx.incoherent_impls(ty).iter().copied(); - #[allow(clippy::iter_empty)] let empty = || [].iter().copied(); match name { "bool" => single(BoolSimplifiedType), diff --git a/tests/ui/iter_empty.fixed b/tests/ui/iter_empty.fixed index 690da5a8761..ad1e106d2b1 100644 --- a/tests/ui/iter_empty.fixed +++ b/tests/ui/iter_empty.fixed @@ -13,6 +13,14 @@ fn array() { // Don't trigger on non-iter methods let _: Option = None.clone(); let _: [String; 0] = [].clone(); + + // Don't trigger on match or if branches + let _ = match 123 { + 123 => [].iter(), + _ => ["test"].iter(), + }; + + let _ = if false { ["test"].iter() } else { [].iter() }; } macro_rules! in_macros { diff --git a/tests/ui/iter_empty.rs b/tests/ui/iter_empty.rs index f8b56898f2d..625149b5da5 100644 --- a/tests/ui/iter_empty.rs +++ b/tests/ui/iter_empty.rs @@ -13,6 +13,14 @@ fn array() { // Don't trigger on non-iter methods let _: Option = None.clone(); let _: [String; 0] = [].clone(); + + // Don't trigger on match or if branches + let _ = match 123 { + 123 => [].iter(), + _ => ["test"].iter(), + }; + + let _ = if false { ["test"].iter() } else { [].iter() }; } macro_rules! in_macros { diff --git a/tests/ui/iter_once.fixed b/tests/ui/iter_once.fixed index 0c82ab20be1..0495bc47e4b 100644 --- a/tests/ui/iter_once.fixed +++ b/tests/ui/iter_once.fixed @@ -13,6 +13,14 @@ fn array() { // Don't trigger on non-iter methods let _: Option = Some("test".to_string()).clone(); let _: [String; 1] = ["test".to_string()].clone(); + + // Don't trigger on match or if branches + let _ = match 123 { + 123 => [].iter(), + _ => ["test"].iter(), + }; + + let _ = if false { ["test"].iter() } else { [].iter() }; } macro_rules! in_macros { diff --git a/tests/ui/iter_once.rs b/tests/ui/iter_once.rs index d561bf27c1d..96641109bb9 100644 --- a/tests/ui/iter_once.rs +++ b/tests/ui/iter_once.rs @@ -13,6 +13,14 @@ fn array() { // Don't trigger on non-iter methods let _: Option = Some("test".to_string()).clone(); let _: [String; 1] = ["test".to_string()].clone(); + + // Don't trigger on match or if branches + let _ = match 123 { + 123 => [].iter(), + _ => ["test"].iter(), + }; + + let _ = if false { ["test"].iter() } else { [].iter() }; } macro_rules! in_macros {