From 20670f78fdd63fbf1597457fcb35a562a428e0e9 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Sun, 8 Jun 2025 01:13:18 +0800 Subject: [PATCH] fix: `iter_on_single_item` FP on let stmt with type annotation --- .../iter_on_single_or_empty_collections.rs | 6 +++-- tests/ui/iter_on_single_items.fixed | 27 ++++++++++++++----- tests/ui/iter_on_single_items.rs | 27 ++++++++++++++----- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index bda74ab173b6..83e565562af0 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -10,6 +10,7 @@ use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::hir_id::HirId; use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::LateContext; +use rustc_middle::ty::Binder; use rustc_span::Symbol; use super::{ITER_ON_EMPTY_COLLECTIONS, ITER_ON_SINGLE_ITEMS}; @@ -38,7 +39,7 @@ fn is_arg_ty_unified_in_fn<'tcx>( is_method: bool, ) -> bool { let arg_id_in_args = args.into_iter().position(|e| e.hir_id == arg_id).unwrap(); - let Some(arg_ty_in_args) = fn_sig.input(arg_id_in_args).map(|binder| binder.skip_binder()) else { + let Some(arg_ty_in_args) = fn_sig.input(arg_id_in_args).map(Binder::skip_binder) else { return false; }; @@ -97,7 +98,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method | ExprKind::Break(_, _) => true, _ => false, }, - Some((Node::Stmt(_) | Node::LetStmt(_), _)) => false, + Some((Node::LetStmt(let_stmt), _)) => let_stmt.ty.is_some(), + Some((Node::Stmt(_), _)) => false, _ => true, }; diff --git a/tests/ui/iter_on_single_items.fixed b/tests/ui/iter_on_single_items.fixed index bdab6121b1f6..044037aac2e3 100644 --- a/tests/ui/iter_on_single_items.fixed +++ b/tests/ui/iter_on_single_items.fixed @@ -67,13 +67,26 @@ fn main() { in_macros!(); } -fn issue14981() { +mod issue14981 { use std::option::IntoIter; - fn some_func(_: IntoIter) -> IntoIter { - todo!() - } - some_func(Some(5).into_iter()); + fn takes_into_iter(_: impl IntoIterator) {} - const C: fn(IntoIter) -> IntoIter = as IntoIterator>::into_iter; - C(Some(5).into_iter()); + fn let_stmt() { + macro_rules! x { + ($e:expr) => { + let _: IntoIter = $e; + }; + } + x!(Some(5).into_iter()); + } + + fn fn_ptr() { + fn some_func(_: IntoIter) -> IntoIter { + todo!() + } + some_func(Some(5).into_iter()); + + const C: fn(IntoIter) -> IntoIter = as IntoIterator>::into_iter; + C(Some(5).into_iter()); + } } diff --git a/tests/ui/iter_on_single_items.rs b/tests/ui/iter_on_single_items.rs index 40ed6d3ec1a6..c925d0e480fa 100644 --- a/tests/ui/iter_on_single_items.rs +++ b/tests/ui/iter_on_single_items.rs @@ -67,13 +67,26 @@ fn main() { in_macros!(); } -fn issue14981() { +mod issue14981 { use std::option::IntoIter; - fn some_func(_: IntoIter) -> IntoIter { - todo!() - } - some_func(Some(5).into_iter()); + fn takes_into_iter(_: impl IntoIterator) {} - const C: fn(IntoIter) -> IntoIter = as IntoIterator>::into_iter; - C(Some(5).into_iter()); + fn let_stmt() { + macro_rules! x { + ($e:expr) => { + let _: IntoIter = $e; + }; + } + x!(Some(5).into_iter()); + } + + fn fn_ptr() { + fn some_func(_: IntoIter) -> IntoIter { + todo!() + } + some_func(Some(5).into_iter()); + + const C: fn(IntoIter) -> IntoIter = as IntoIterator>::into_iter; + C(Some(5).into_iter()); + } }