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::{Expr, ExprKind};
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
9 use std::collections::BinaryHeap;
11 declare_clippy_lint! {
13 /// Checks for tuple structs initialized with field syntax.
14 /// It will however not lint if a base initializer is present.
15 /// The lint will also ignore code in macros.
17 /// ### Why is this bad?
18 /// This may be confusing to the uninitiated and adds no
19 /// benefit as opposed to tuple initializers
23 /// struct TupleStruct(u8, u16);
25 /// let _ = TupleStruct {
30 /// // should be written as
31 /// let base = TupleStruct(1, 23);
33 /// // This is OK however
34 /// let _ = TupleStruct { 0: 42, ..base };
36 #[clippy::version = "1.59.0"]
37 pub INIT_NUMBERED_FIELDS,
39 "numbered fields in tuple struct initializer"
42 declare_lint_pass!(NumberedFields => [INIT_NUMBERED_FIELDS]);
44 impl<'tcx> LateLintPass<'tcx> for NumberedFields {
45 fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
46 if let ExprKind::Struct(path, fields, None) = e.kind {
48 && !e.span.from_expansion()
51 .all(|f| f.ident.as_str().as_bytes().iter().all(u8::is_ascii_digit))
53 let expr_spans = fields
55 .map(|f| (Reverse(f.ident.as_str().parse::<usize>().unwrap()), f.expr.span))
56 .collect::<BinaryHeap<_>>();
57 let mut appl = Applicability::MachineApplicable;
58 let snippet = format!(
60 snippet_with_applicability(cx, path.span(), "..", &mut appl),
63 .map(|(_, span)| snippet_with_applicability(cx, span, "..", &mut appl))
64 .intersperse(Cow::Borrowed(", "))
71 "used a field initializer for a tuple struct",