diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index 8bb3a57ba9a..ae0b5140316 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -149,6 +149,7 @@ The minimum rust version that the project supports
* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
+* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions)
## `cognitive-complexity-threshold`
diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs
index 6564666d186..bd983306508 100644
--- a/clippy_lints/src/tuple_array_conversions.rs
+++ b/clippy_lints/src/tuple_array_conversions.rs
@@ -4,9 +4,8 @@ use clippy_utils::{
msrvs::{self, Msrv},
path_to_local,
};
-use itertools::Itertools;
use rustc_ast::LitKind;
-use rustc_hir::{Expr, ExprKind, Node, Pat};
+use rustc_hir::{Expr, ExprKind, HirId, Node, Pat};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::{lint::in_external_macro, ty};
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -17,8 +16,8 @@ declare_clippy_lint! {
/// Checks for tuple<=>array conversions that are not done with `.into()`.
///
/// ### Why is this bad?
- /// It's overly complex. `.into()` works for tuples<=>arrays with less than 13 elements and
- /// conveys the intent a lot better, while also leaving less room for bugs!
+ /// It's unnecessary complexity. `.into()` works for tuples<=>arrays at or below 12 elements and
+ /// conveys the intent a lot better, while also leaving less room for hard to spot bugs!
///
/// ### Example
/// ```rust,ignore
@@ -45,26 +44,28 @@ pub struct TupleArrayConversions {
impl LateLintPass<'_> for TupleArrayConversions {
fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if !in_external_macro(cx.sess(), expr.span) && self.msrv.meets(msrvs::TUPLE_ARRAY_CONVERSIONS) {
- _ = check_array(cx, expr) || check_tuple(cx, expr);
+ match expr.kind {
+ ExprKind::Array(elements) if (1..=12).contains(&elements.len()) => check_array(cx, expr, elements),
+ ExprKind::Tup(elements) if (1..=12).contains(&elements.len()) => check_tuple(cx, expr, elements),
+ _ => {},
+ }
}
}
extract_msrv_attr!(LateContext);
}
-fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
- let ExprKind::Array(elements) = expr.kind else {
- return false;
- };
- if !(1..=12).contains(&elements.len()) {
- return false;
- }
-
- if let Some(locals) = path_to_locals(cx, &elements.iter().collect_vec())
- && let [first, rest @ ..] = &*locals
- && let Node::Pat(first_pat) = first
- && let first_id = parent_pat(cx, first_pat).hir_id
- && rest.iter().chain(once(first)).all(|local| {
+#[expect(
+ clippy::blocks_in_if_conditions,
+ reason = "not a FP, but this is much easier to understand"
+)]
+fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) {
+ if should_lint(
+ cx,
+ elements,
+ // This is cursed.
+ Some,
+ |(first_id, local)| {
if let Node::Pat(pat) = local
&& let parent = parent_pat(cx, pat)
&& parent.hir_id == first_id
@@ -76,27 +77,18 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
}
false
- })
- {
- return emit_lint(cx, expr, ToType::Array);
- }
+ },
+ ) || should_lint(
+ cx,
+ elements,
+ |(i, expr)| {
+ if let ExprKind::Field(path, field) = expr.kind && field.as_str() == i.to_string() {
+ return Some((i, path));
+ };
- if let Some(elements) = elements
- .iter()
- .enumerate()
- .map(|(i, expr)| {
- if let ExprKind::Field(path, field) = expr.kind && field.as_str() == i.to_string() {
- return Some(path);
- };
-
- None
- })
- .collect::