|
1 | 1 | use clippy_config::Conf; |
2 | 2 | use clippy_utils::diagnostics::span_lint_and_help; |
3 | | -use clippy_utils::is_from_proc_macro; |
4 | 3 | use clippy_utils::msrvs::{self, Msrv}; |
5 | 4 | 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}; |
7 | 7 | use itertools::Itertools; |
8 | 8 | use rustc_ast::LitKind; |
9 | | -use rustc_hir::{Expr, ExprKind, Node, PatKind}; |
| 9 | +use rustc_hir::{Expr, ExprKind, HirId, Node, PatKind}; |
10 | 10 | use rustc_lint::{LateContext, LateLintPass, LintContext}; |
11 | 11 | use rustc_middle::ty::{self, Ty}; |
12 | 12 | use rustc_session::impl_lint_pass; |
@@ -170,6 +170,7 @@ fn all_bindings_are_for_conv<'tcx>( |
170 | 170 | && locals |
171 | 171 | .iter() |
172 | 172 | .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)) |
173 | 174 | && local_parents.first().is_some_and(|node| { |
174 | 175 | let Some(ty) = match node { |
175 | 176 | Node::Pat(pat) => Some(pat.hir_id), |
@@ -208,3 +209,22 @@ impl PartialEq<PatKind<'_>> for ToType { |
208 | 209 | } |
209 | 210 | } |
210 | 211 | } |
| 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 | +} |
0 commit comments