1 use clippy_utils
::diagnostics
::span_lint_and_sugg
;
2 use clippy_utils
::in_macro
;
3 use if_chain
::if_chain
;
4 use rustc_ast
::ast
::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind}
;
5 use rustc_errors
::Applicability
;
6 use rustc_lint
::{EarlyContext, EarlyLintPass}
;
7 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
8 use rustc_span
::symbol
::kw
;
11 declare_clippy_lint
! {
12 /// **What it does:** The lint checks for `self` in fn parameters that
13 /// specify the `Self`-type explicitly
14 /// **Why is this bad?** Increases the amount and decreases the readability of code
16 /// **Known problems:** None
28 /// pub fn bytes(self: Self) -> usize {
30 /// Self::I32 | Self::F32 => 4,
31 /// Self::I64 | Self::F64 => 8,
37 /// Could be rewritten as
48 /// pub fn bytes(self) -> usize {
50 /// Self::I32 | Self::F32 => 4,
51 /// Self::I64 | Self::F64 => 8,
56 pub NEEDLESS_ARBITRARY_SELF_TYPE
,
58 "type of `self` parameter is already by default `Self`"
61 declare_lint_pass
!(NeedlessArbitrarySelfType
=> [NEEDLESS_ARBITRARY_SELF_TYPE
]);
64 Ref(Option
<Lifetime
>),
68 fn check_param_inner(cx
: &EarlyContext
<'_
>, path
: &Path
, span
: Span
, binding_mode
: &Mode
, mutbl
: Mutability
) {
70 if let [segment
] = &path
.segments
[..];
71 if segment
.ident
.name
== kw
::SelfUpper
;
73 // In case we have a named lifetime, we check if the name comes from expansion.
74 // If it does, at this point we know the rest of the parameter was written by the user,
75 // so let them decide what the name of the lifetime should be.
76 // See #6089 for more details.
77 let mut applicability
= Applicability
::MachineApplicable
;
78 let self_param
= match (binding_mode
, mutbl
) {
79 (Mode
::Ref(None
), Mutability
::Mut
) => "&mut self".to_string(),
80 (Mode
::Ref(Some(lifetime
)), Mutability
::Mut
) => {
81 if in_macro(lifetime
.ident
.span
) {
82 applicability
= Applicability
::HasPlaceholders
;
83 "&'_ mut self".to_string()
85 format
!("&{} mut self", &lifetime
.ident
.name
)
88 (Mode
::Ref(None
), Mutability
::Not
) => "&self".to_string(),
89 (Mode
::Ref(Some(lifetime
)), Mutability
::Not
) => {
90 if in_macro(lifetime
.ident
.span
) {
91 applicability
= Applicability
::HasPlaceholders
;
92 "&'_ self".to_string()
94 format
!("&{} self", &lifetime
.ident
.name
)
97 (Mode
::Value
, Mutability
::Mut
) => "mut self".to_string(),
98 (Mode
::Value
, Mutability
::Not
) => "self".to_string(),
103 NEEDLESS_ARBITRARY_SELF_TYPE
,
105 "the type of the `self` parameter does not need to be arbitrary",
106 "consider to change this parameter to",
114 impl EarlyLintPass
for NeedlessArbitrarySelfType
{
115 fn check_param(&mut self, cx
: &EarlyContext
<'_
>, p
: &Param
) {
116 // Bail out if the parameter it's not a receiver or was not written by the user
117 if !p
.is_self() || in_macro(p
.span
) {
122 TyKind
::Path(None
, path
) => {
123 if let PatKind
::Ident(BindingMode
::ByValue(mutbl
), _
, _
) = p
.pat
.kind
{
124 check_param_inner(cx
, path
, p
.span
.to(p
.ty
.span
), &Mode
::Value
, mutbl
)
127 TyKind
::Rptr(lifetime
, mut_ty
) => {
129 if let TyKind
::Path(None
, path
) = &mut_ty
.ty
.kind
;
130 if let PatKind
::Ident(BindingMode
::ByValue(Mutability
::Not
), _
, _
) = p
.pat
.kind
;
132 check_param_inner(cx
, path
, p
.span
.to(p
.ty
.span
), &Mode
::Ref(*lifetime
), mut_ty
.mutbl
)