Skip to content

Commit 3a67f16

Browse files
committed
fix: tuple_array_conversions FP when binded vars are used before conversion
1 parent 64f43bf commit 3a67f16

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

clippy_lints/src/tuple_array_conversions.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use clippy_config::Conf;
22
use clippy_utils::diagnostics::span_lint_and_help;
3-
use clippy_utils::is_from_proc_macro;
43
use clippy_utils::msrvs::{self, Msrv};
54
use clippy_utils::res::MaybeResPath;
6-
use clippy_utils::visitors::for_each_local_use_after_expr;
5+
use clippy_utils::visitors::{for_each_expr, for_each_local_use_after_expr};
6+
use clippy_utils::{get_enclosing_block, is_from_proc_macro};
77
use itertools::Itertools;
88
use rustc_ast::LitKind;
9-
use rustc_hir::{Expr, ExprKind, Node, PatKind};
9+
use rustc_hir::{Expr, ExprKind, HirId, Node, PatKind};
1010
use rustc_lint::{LateContext, LateLintPass, LintContext};
1111
use rustc_middle::ty::{self, Ty};
1212
use rustc_session::impl_lint_pass;
@@ -170,6 +170,7 @@ fn all_bindings_are_for_conv<'tcx>(
170170
&& locals
171171
.iter()
172172
.all(|&l| for_each_local_use_after_expr(cx, l, expr.hir_id, |_| ControlFlow::Break::<()>(())).is_continue())
173+
&& !locals.iter().any(|&l| local_used_until_expr(cx, l, expr.hir_id))
173174
&& local_parents.first().is_some_and(|node| {
174175
let Some(ty) = match node {
175176
Node::Pat(pat) => Some(pat.hir_id),
@@ -208,3 +209,22 @@ impl PartialEq<PatKind<'_>> for ToType {
208209
}
209210
}
210211
}
212+
213+
fn local_used_until_expr(cx: &LateContext<'_>, local_id: HirId, expr_id: HirId) -> bool {
214+
let Some(b) = get_enclosing_block(cx, local_id) else {
215+
return false;
216+
};
217+
218+
for_each_expr(cx, b, |e| {
219+
if e.hir_id == expr_id {
220+
return ControlFlow::Break(false);
221+
}
222+
223+
if e.res_local_id() == Some(local_id) {
224+
return ControlFlow::Break(true);
225+
}
226+
227+
ControlFlow::Continue(())
228+
})
229+
.unwrap_or(false)
230+
}

tests/ui/tuple_array_conversions.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,19 @@ fn msrv_juust_right() {
116116
let x = &[1, 2];
117117
let x = (x[0], x[1]);
118118
}
119+
120+
fn issue16192() {
121+
fn do_something(tuple: (u32, u32)) {}
122+
fn produce_array() -> [u32; 2] {
123+
[1, 2]
124+
}
125+
126+
let [a, b] = produce_array();
127+
for tuple in [(a, b), (b, a)] {
128+
do_something(tuple);
129+
}
130+
131+
let [a, b] = produce_array();
132+
let x = b;
133+
do_something((a, b));
134+
}

0 commit comments

Comments
 (0)