]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
bump version to 1.79.0+dfsg1-1~bpo12+pve2
[rustc.git] / src / tools / clippy / clippy_lints / src / needless_arbitrary_self_type.rs
CommitLineData
cdc7bbd5 1use clippy_utils::diagnostics::span_lint_and_sugg;
e8be2606 2use rustc_ast::ast::{BindingMode, ByRef, Lifetime, Mutability, Param, PatKind, Path, TyKind};
f20569fa
XL
3use rustc_errors::Applicability;
4use rustc_lint::{EarlyContext, EarlyLintPass};
4b012472 5use rustc_session::declare_lint_pass;
f20569fa
XL
6use rustc_span::symbol::kw;
7use rustc_span::Span;
8
9declare_clippy_lint! {
94222f64
XL
10 /// ### What it does
11 /// The lint checks for `self` in fn parameters that
f20569fa 12 /// specify the `Self`-type explicitly
94222f64
XL
13 /// ### Why is this bad?
14 /// Increases the amount and decreases the readability of code
f20569fa 15 ///
94222f64 16 /// ### Example
ed00b5ec 17 /// ```no_run
f20569fa
XL
18 /// enum ValType {
19 /// I32,
20 /// I64,
21 /// F32,
22 /// F64,
23 /// }
24 ///
25 /// impl ValType {
26 /// pub fn bytes(self: Self) -> usize {
27 /// match self {
28 /// Self::I32 | Self::F32 => 4,
29 /// Self::I64 | Self::F64 => 8,
30 /// }
31 /// }
32 /// }
33 /// ```
34 ///
35 /// Could be rewritten as
36 ///
ed00b5ec 37 /// ```no_run
f20569fa
XL
38 /// enum ValType {
39 /// I32,
40 /// I64,
41 /// F32,
42 /// F64,
43 /// }
44 ///
45 /// impl ValType {
46 /// pub fn bytes(self) -> usize {
47 /// match self {
48 /// Self::I32 | Self::F32 => 4,
49 /// Self::I64 | Self::F64 => 8,
50 /// }
51 /// }
52 /// }
53 /// ```
a2a8927a 54 #[clippy::version = "1.47.0"]
f20569fa
XL
55 pub NEEDLESS_ARBITRARY_SELF_TYPE,
56 complexity,
57 "type of `self` parameter is already by default `Self`"
58}
59
60declare_lint_pass!(NeedlessArbitrarySelfType => [NEEDLESS_ARBITRARY_SELF_TYPE]);
61
62enum Mode {
63 Ref(Option<Lifetime>),
64 Value,
65}
66
67fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mode: &Mode, mutbl: Mutability) {
4b012472
FG
68 if let [segment] = &path.segments[..]
69 && segment.ident.name == kw::SelfUpper
70 {
71 // In case we have a named lifetime, we check if the name comes from expansion.
72 // If it does, at this point we know the rest of the parameter was written by the user,
73 // so let them decide what the name of the lifetime should be.
74 // See #6089 for more details.
75 let mut applicability = Applicability::MachineApplicable;
76 let self_param = match (binding_mode, mutbl) {
77 (Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(),
78 (Mode::Ref(Some(lifetime)), Mutability::Mut) => {
79 if lifetime.ident.span.from_expansion() {
80 applicability = Applicability::HasPlaceholders;
81 "&'_ mut self".to_string()
82 } else {
83 format!("&{} mut self", &lifetime.ident.name)
84 }
85 },
86 (Mode::Ref(None), Mutability::Not) => "&self".to_string(),
87 (Mode::Ref(Some(lifetime)), Mutability::Not) => {
88 if lifetime.ident.span.from_expansion() {
89 applicability = Applicability::HasPlaceholders;
90 "&'_ self".to_string()
91 } else {
92 format!("&{} self", &lifetime.ident.name)
93 }
94 },
95 (Mode::Value, Mutability::Mut) => "mut self".to_string(),
96 (Mode::Value, Mutability::Not) => "self".to_string(),
97 };
f20569fa 98
4b012472
FG
99 span_lint_and_sugg(
100 cx,
101 NEEDLESS_ARBITRARY_SELF_TYPE,
102 span,
103 "the type of the `self` parameter does not need to be arbitrary",
104 "consider to change this parameter to",
105 self_param,
106 applicability,
107 );
f20569fa
XL
108 }
109}
110
111impl EarlyLintPass for NeedlessArbitrarySelfType {
112 fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) {
113 // Bail out if the parameter it's not a receiver or was not written by the user
a2a8927a 114 if !p.is_self() || p.span.from_expansion() {
f20569fa
XL
115 return;
116 }
117
118 match &p.ty.kind {
119 TyKind::Path(None, path) => {
e8be2606 120 if let PatKind::Ident(BindingMode(ByRef::No, mutbl), _, _) = p.pat.kind {
17df50a5 121 check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl);
f20569fa
XL
122 }
123 },
9c376795 124 TyKind::Ref(lifetime, mut_ty) => {
4b012472 125 if let TyKind::Path(None, path) = &mut_ty.ty.kind
e8be2606 126 && let PatKind::Ident(BindingMode::NONE, _, _) = p.pat.kind
4b012472
FG
127 {
128 check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
f20569fa
XL
129 }
130 },
131 _ => {},
132 }
133 }
134}