From bfcc8ba444180dfc12bb113d1d500b81c9e87956 Mon Sep 17 00:00:00 2001
From: Catherine <114838443+Centri3@users.noreply.github.com>
Date: Sat, 24 Jun 2023 07:40:09 -0500
Subject: New lint `tuple_array_conversions`
---
clippy_lints/src/tuple_array_conversions.rs | 187 ++++++++++++++++++++++++++++
1 file changed, 187 insertions(+)
create mode 100644 clippy_lints/src/tuple_array_conversions.rs
(limited to 'clippy_lints/src/tuple_array_conversions.rs')
diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs
new file mode 100644
index 00000000000..9640083f764
--- /dev/null
+++ b/clippy_lints/src/tuple_array_conversions.rs
@@ -0,0 +1,187 @@
+use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, path_to_local};
+use rustc_hir::*;
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::{lint::in_external_macro, ty};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// ### Why is this bad?
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// let t1 = &[(1, 2), (3, 4)];
+ /// let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect();
+ /// ```
+ /// Use instead:
+ /// ```rust,ignore
+ /// let t1 = &[(1, 2), (3, 4)];
+ /// let v1: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect();
+ /// ```
+ #[clippy::version = "1.72.0"]
+ pub TUPLE_ARRAY_CONVERSIONS,
+ complexity,
+ "default lint description"
+}
+declare_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]);
+
+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) {
+ _ = check_array(cx, expr) || check_tuple(cx, expr);
+ }
+ }
+}
+
+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)
+ && locals.iter().all(|local| {
+ matches!(
+ local,
+ Node::Pat(pat) if matches!(
+ cx.typeck_results().pat_ty(backtrack_pat(cx, pat)).peel_refs().kind(),
+ ty::Tuple(_),
+ ),
+ )
+ })
+ {
+ return emit_lint(cx, expr, ToType::Array);
+ }
+
+ if let Some(elements) = elements
+ .iter()
+ .map(|expr| {
+ if let ExprKind::Field(path, _) = expr.kind {
+ return Some(path);
+ };
+
+ None
+ })
+ .collect::