]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/init_numbered_fields.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / src / tools / clippy / clippy_lints / src / init_numbered_fields.rs
CommitLineData
a2a8927a 1use clippy_utils::diagnostics::span_lint_and_sugg;
31ef2f64 2use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
a2a8927a 3use rustc_errors::Applicability;
04454e1e 4use rustc_hir::def::{DefKind, Res};
a2a8927a
XL
5use rustc_hir::{Expr, ExprKind};
6use rustc_lint::{LateContext, LateLintPass};
4b012472 7use rustc_session::declare_lint_pass;
a2a8927a
XL
8use std::borrow::Cow;
9use std::cmp::Reverse;
10use std::collections::BinaryHeap;
11
12declare_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
ed00b5ec 23 /// ```no_run
a2a8927a
XL
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
43declare_lint_pass!(NumberedFields => [INIT_NUMBERED_FIELDS]);
44
45impl<'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()
5099ac24 49 && !e.span.from_expansion()
a2a8927a
XL
50 && fields
51 .iter()
52 .all(|f| f.ident.as_str().as_bytes().iter().all(u8::is_ascii_digit))
781aab86 53 && !matches!(cx.qpath_res(path, e.hir_id), Res::Def(DefKind::TyAlias, ..))
a2a8927a
XL
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()
31ef2f64 65 .map(|(_, span)| snippet_with_context(cx, span, path.span().ctxt(), "..", &mut appl).0)
a2a8927a
XL
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",
add651ee 74 "try",
a2a8927a
XL
75 snippet,
76 appl,
77 );
78 }
79 }
80 }
81}