]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/init_numbered_fields.rs
bump version to 1.79.0+dfsg1-1~bpo12+pve2
[rustc.git] / src / tools / clippy / clippy_lints / src / init_numbered_fields.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet_with_applicability;
3 use rustc_errors::Applicability;
4 use rustc_hir::def::{DefKind, Res};
5 use rustc_hir::{Expr, ExprKind};
6 use rustc_lint::{LateContext, LateLintPass};
7 use rustc_session::declare_lint_pass;
8 use std::borrow::Cow;
9 use std::cmp::Reverse;
10 use std::collections::BinaryHeap;
11
12 declare_clippy_lint! {
13 /// ### What it does
14 /// Checks for tuple structs initialized with field syntax.
15 /// It will however not lint if a base initializer is present.
16 /// The lint will also ignore code in macros.
17 ///
18 /// ### Why is this bad?
19 /// This may be confusing to the uninitiated and adds no
20 /// benefit as opposed to tuple initializers
21 ///
22 /// ### Example
23 /// ```no_run
24 /// struct TupleStruct(u8, u16);
25 ///
26 /// let _ = TupleStruct {
27 /// 0: 1,
28 /// 1: 23,
29 /// };
30 ///
31 /// // should be written as
32 /// let base = TupleStruct(1, 23);
33 ///
34 /// // This is OK however
35 /// let _ = TupleStruct { 0: 42, ..base };
36 /// ```
37 #[clippy::version = "1.59.0"]
38 pub INIT_NUMBERED_FIELDS,
39 style,
40 "numbered fields in tuple struct initializer"
41 }
42
43 declare_lint_pass!(NumberedFields => [INIT_NUMBERED_FIELDS]);
44
45 impl<'tcx> LateLintPass<'tcx> for NumberedFields {
46 fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
47 if let ExprKind::Struct(path, fields, None) = e.kind {
48 if !fields.is_empty()
49 && !e.span.from_expansion()
50 && fields
51 .iter()
52 .all(|f| f.ident.as_str().as_bytes().iter().all(u8::is_ascii_digit))
53 && !matches!(cx.qpath_res(path, e.hir_id), Res::Def(DefKind::TyAlias, ..))
54 {
55 let expr_spans = fields
56 .iter()
57 .map(|f| (Reverse(f.ident.as_str().parse::<usize>().unwrap()), f.expr.span))
58 .collect::<BinaryHeap<_>>();
59 let mut appl = Applicability::MachineApplicable;
60 let snippet = format!(
61 "{}({})",
62 snippet_with_applicability(cx, path.span(), "..", &mut appl),
63 expr_spans
64 .into_iter_sorted()
65 .map(|(_, span)| snippet_with_applicability(cx, span, "..", &mut appl))
66 .intersperse(Cow::Borrowed(", "))
67 .collect::<String>()
68 );
69 span_lint_and_sugg(
70 cx,
71 INIT_NUMBERED_FIELDS,
72 e.span,
73 "used a field initializer for a tuple struct",
74 "try",
75 snippet,
76 appl,
77 );
78 }
79 }
80 }
81 }