From e0a4988fcc716e349fd801d98182c0d984a2ee3f Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Tue, 4 Aug 2020 20:23:14 +0200 Subject: [PATCH] Lint against `Self` as an arbitrary self type Fixes #5861 --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 ++ clippy_lints/src/needless_fn_self_type.rs | 64 +++++++++++++++++++++++ clippy_lints/src/trait_bounds.rs | 2 +- src/lintlist/mod.rs | 7 +++ tests/ui/needless_fn_self_type.rs | 26 +++++++++ tests/ui/needless_fn_self_type.stderr | 11 ++++ 7 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/needless_fn_self_type.rs create mode 100644 tests/ui/needless_fn_self_type.rs create mode 100644 tests/ui/needless_fn_self_type.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index bfe896d5efa..179ecee03da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1622,6 +1622,7 @@ Released 2018-09-13 [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main +[`needless_fn_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_fn_self_type [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 81864340f1a..80c85e70e89 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -254,6 +254,7 @@ macro_rules! declare_clippy_lint { mod needless_borrow; mod needless_borrowed_ref; mod needless_continue; +mod needless_fn_self_type; mod needless_pass_by_value; mod needless_update; mod neg_cmp_op_on_partial_ord; @@ -722,6 +723,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &needless_borrow::NEEDLESS_BORROW, &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, &needless_continue::NEEDLESS_CONTINUE, + &needless_fn_self_type::NEEDLESS_FN_SELF_TYPE, &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, &needless_update::NEEDLESS_UPDATE, &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, @@ -1027,6 +1029,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); store.register_early_pass(|| box precedence::Precedence); store.register_early_pass(|| box needless_continue::NeedlessContinue); + store.register_early_pass(|| box needless_fn_self_type::NeedlessFnSelfType); store.register_early_pass(|| box redundant_static_lifetimes::RedundantStaticLifetimes); store.register_late_pass(|| box cargo_common_metadata::CargoCommonMetadata); store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions); @@ -1374,6 +1377,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&needless_bool::BOOL_COMPARISON), LintId::of(&needless_bool::NEEDLESS_BOOL), LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), + LintId::of(&needless_fn_self_type::NEEDLESS_FN_SELF_TYPE), LintId::of(&needless_update::NEEDLESS_UPDATE), LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), LintId::of(&neg_multiply::NEG_MULTIPLY), @@ -1534,6 +1538,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), LintId::of(&misc_early::REDUNDANT_PATTERN), LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), + LintId::of(&needless_fn_self_type::NEEDLESS_FN_SELF_TYPE), LintId::of(&neg_multiply::NEG_MULTIPLY), LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), diff --git a/clippy_lints/src/needless_fn_self_type.rs b/clippy_lints/src/needless_fn_self_type.rs new file mode 100644 index 00000000000..050a03467fb --- /dev/null +++ b/clippy_lints/src/needless_fn_self_type.rs @@ -0,0 +1,64 @@ +use crate::utils::span_lint_and_help; +use if_chain::if_chain; +use rustc_ast::ast::{Param, TyKind}; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** The lint checks for `self` fn fn parameters that explicitly + /// specify the `Self`-type explicitly + /// **Why is this bad?** Increases the amount and decreases the readability of code + /// + /// **Known problems:** None + /// + /// **Example:** + /// ```rust + /// impl ValType { + /// pub fn bytes(self: Self) -> usize { + /// match self { + /// Self::I32 | Self::F32 => 4, + /// Self::I64 | Self::F64 => 8, + /// } + /// } + /// } + /// ``` + /// + /// Could be rewritten as + /// + /// ```rust + /// impl ValType { + /// pub fn bytes(self) -> usize { + /// match self { + /// Self::I32 | Self::F32 => 4, + /// Self::I64 | Self::F64 => 8, + /// } + /// } + /// } + /// ``` + pub NEEDLESS_FN_SELF_TYPE, + style, + "type of `self` parameter is already by default `Self`" +} + +declare_lint_pass!(NeedlessFnSelfType => [NEEDLESS_FN_SELF_TYPE]); + +impl EarlyLintPass for NeedlessFnSelfType { + fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) { + if_chain! { + if p.is_self(); + if let TyKind::Path(None, path) = &p.ty.kind; + if let Some(segment) = path.segments.first(); + if segment.ident.as_str() == sym!(Self).as_str(); + then { + span_lint_and_help( + cx, + NEEDLESS_FN_SELF_TYPE, + p.ty.span, + "the type of the `self` parameter is already by default `Self`", + None, + "consider removing the type specification", + ); + } + } + } +} diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 06631f89f27..d4acf8df46d 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -50,7 +50,7 @@ /// fn func(arg: T) {} /// ``` /// or - /// /// + /// /// ```rust /// fn func(arg: T) where T: Clone + Default {} /// ``` diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index b64c6e54409..a20e410f79b 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1501,6 +1501,13 @@ deprecation: None, module: "doc", }, + Lint { + name: "needless_fn_self_type", + group: "style", + desc: "type of `self` parameter is already by default `Self`", + deprecation: None, + module: "needless_fn_self_type", + }, Lint { name: "needless_lifetimes", group: "complexity", diff --git a/tests/ui/needless_fn_self_type.rs b/tests/ui/needless_fn_self_type.rs new file mode 100644 index 00000000000..12bb84582ff --- /dev/null +++ b/tests/ui/needless_fn_self_type.rs @@ -0,0 +1,26 @@ +#![warn(clippy::style, clippy::needless_fn_self_type)] + +pub enum ValType { + I32, + I64, + F32, + F64, +} + +impl ValType { + pub fn bytes_bad(self: Self) -> usize { + match self { + Self::I32 | Self::F32 => 4, + Self::I64 | Self::F64 => 8, + } + } + + pub fn bytes_good(self) -> usize { + match self { + Self::I32 | Self::F32 => 4, + Self::I64 | Self::F64 => 8, + } + } +} + +fn main() {} diff --git a/tests/ui/needless_fn_self_type.stderr b/tests/ui/needless_fn_self_type.stderr new file mode 100644 index 00000000000..703705c7842 --- /dev/null +++ b/tests/ui/needless_fn_self_type.stderr @@ -0,0 +1,11 @@ +error: the type of the `self` parameter is already by default `Self` + --> $DIR/needless_fn_self_type.rs:11:28 + | +LL | pub fn bytes_bad(self: Self) -> usize { + | ^^^^ + | + = note: `-D clippy::needless-fn-self-type` implied by `-D warnings` + = help: consider removing the type specification + +error: aborting due to previous error + -- 2.44.0