1 use crate::utils::span_lint_and_sugg;
2 use if_chain::if_chain;
3 use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind};
4 use rustc_errors::Applicability;
5 use rustc_lint::{EarlyContext, EarlyLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7 use rustc_span::symbol::kw;
10 declare_clippy_lint! {
11 /// **What it does:** The lint checks for `self` in fn parameters that
12 /// specify the `Self`-type explicitly
13 /// **Why is this bad?** Increases the amount and decreases the readability of code
15 /// **Known problems:** None
27 /// pub fn bytes(self: Self) -> usize {
29 /// Self::I32 | Self::F32 => 4,
30 /// Self::I64 | Self::F64 => 8,
36 /// Could be rewritten as
47 /// pub fn bytes(self) -> usize {
49 /// Self::I32 | Self::F32 => 4,
50 /// Self::I64 | Self::F64 => 8,
55 pub NEEDLESS_ARBITRARY_SELF_TYPE,
57 "type of `self` parameter is already by default `Self`"
60 declare_lint_pass!(NeedlessArbitrarySelfType => [NEEDLESS_ARBITRARY_SELF_TYPE]);
63 Ref(Option<Lifetime>),
67 fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mode: &Mode, mutbl: Mutability) {
69 if let [segment] = &path.segments[..];
70 if segment.ident.name == kw::SelfUpper;
72 let self_param = match (binding_mode, mutbl) {
73 (Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(),
74 (Mode::Ref(Some(lifetime)), Mutability::Mut) => format!("&{} mut self", &lifetime.ident.name),
75 (Mode::Ref(None), Mutability::Not) => "&self".to_string(),
76 (Mode::Ref(Some(lifetime)), Mutability::Not) => format!("&{} self", &lifetime.ident.name),
77 (Mode::Value, Mutability::Mut) => "mut self".to_string(),
78 (Mode::Value, Mutability::Not) => "self".to_string(),
83 NEEDLESS_ARBITRARY_SELF_TYPE,
85 "the type of the `self` parameter does not need to be arbitrary",
86 "consider to change this parameter to",
88 Applicability::MachineApplicable,
94 impl EarlyLintPass for NeedlessArbitrarySelfType {
95 fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) {
101 TyKind::Path(None, path) => {
102 if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind {
103 check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl)
106 TyKind::Rptr(lifetime, mut_ty) => {
108 if let TyKind::Path(None, path) = &mut_ty.ty.kind;
109 if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind;
111 check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl)