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
;
10 use std
::collections
::BinaryHeap
;
12 declare_clippy_lint
! {
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.
18 /// ### Why is this bad?
19 /// This may be confusing to the uninitiated and adds no
20 /// benefit as opposed to tuple initializers
24 /// struct TupleStruct(u8, u16);
26 /// let _ = TupleStruct {
31 /// // should be written as
32 /// let base = TupleStruct(1, 23);
34 /// // This is OK however
35 /// let _ = TupleStruct { 0: 42, ..base };
37 #[clippy::version = "1.59.0"]
38 pub INIT_NUMBERED_FIELDS
,
40 "numbered fields in tuple struct initializer"
43 declare_lint_pass
!(NumberedFields
=> [INIT_NUMBERED_FIELDS
]);
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
{
49 && !e
.span
.from_expansion()
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
, ..))
55 let expr_spans
= fields
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
!(
62 snippet_with_applicability(cx
, path
.span(), "..", &mut appl
),
65 .map(|(_
, span
)| snippet_with_applicability(cx
, span
, "..", &mut appl
))
66 .intersperse(Cow
::Borrowed(", "))
73 "used a field initializer for a tuple struct",