diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index 5d0945bece55..db26e567ddc3 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -1,12 +1,12 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::is_from_proc_macro; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeResPath; -use clippy_utils::visitors::for_each_local_use_after_expr; +use clippy_utils::visitors::{for_each_expr, for_each_local_use_after_expr}; +use clippy_utils::{get_enclosing_block, is_from_proc_macro}; use itertools::Itertools; use rustc_ast::LitKind; -use rustc_hir::{Expr, ExprKind, Node, PatKind}; +use rustc_hir::{Expr, ExprKind, HirId, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; @@ -170,6 +170,7 @@ fn all_bindings_are_for_conv<'tcx>( && locals .iter() .all(|&l| for_each_local_use_after_expr(cx, l, expr.hir_id, |_| ControlFlow::Break::<()>(())).is_continue()) + && !locals.iter().any(|&l| local_used_until_expr(cx, l, expr.hir_id)) && local_parents.first().is_some_and(|node| { let Some(ty) = match node { Node::Pat(pat) => Some(pat.hir_id), @@ -208,3 +209,22 @@ impl PartialEq> for ToType { } } } + +fn local_used_until_expr(cx: &LateContext<'_>, local_id: HirId, expr_id: HirId) -> bool { + let Some(b) = get_enclosing_block(cx, local_id) else { + return false; + }; + + for_each_expr(cx, b, |e| { + if e.hir_id == expr_id { + return ControlFlow::Break(false); + } + + if e.res_local_id() == Some(local_id) { + return ControlFlow::Break(true); + } + + ControlFlow::Continue(()) + }) + .unwrap_or(false) +} diff --git a/tests/ui/tuple_array_conversions.rs b/tests/ui/tuple_array_conversions.rs index 772c41df090e..b127f3dd036d 100644 --- a/tests/ui/tuple_array_conversions.rs +++ b/tests/ui/tuple_array_conversions.rs @@ -116,3 +116,19 @@ fn msrv_juust_right() { let x = &[1, 2]; let x = (x[0], x[1]); } + +fn issue16192() { + fn do_something(tuple: (u32, u32)) {} + fn produce_array() -> [u32; 2] { + [1, 2] + } + + let [a, b] = produce_array(); + for tuple in [(a, b), (b, a)] { + do_something(tuple); + } + + let [a, b] = produce_array(); + let x = b; + do_something((a, b)); +}