Auto merge of #4619 - james9909:unused-self, r=flip1995
Add a lint for unused self changelog: Adds a new lint: `unused_self` Closes #4550.
This commit is contained in:
commit
55e7818a06
@ -1236,6 +1236,7 @@ Released 2018-09-13
|
||||
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
|
||||
[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount
|
||||
[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label
|
||||
[`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
|
||||
[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
|
||||
[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
|
||||
[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||
|
||||
[There are 324 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
[There are 325 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
|
||||
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
|
||||
|
||||
|
@ -39,7 +39,7 @@ declare_lint_pass!(DoubleComparisons => [DOUBLE_COMPARISONS]);
|
||||
|
||||
impl<'a, 'tcx> DoubleComparisons {
|
||||
#[allow(clippy::similar_names)]
|
||||
fn check_binop(self, cx: &LateContext<'a, 'tcx>, op: BinOpKind, lhs: &'tcx Expr, rhs: &'tcx Expr, span: Span) {
|
||||
fn check_binop(cx: &LateContext<'a, 'tcx>, op: BinOpKind, lhs: &'tcx Expr, rhs: &'tcx Expr, span: Span) {
|
||||
let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (&lhs.kind, &rhs.kind) {
|
||||
(ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => {
|
||||
(lb.node, llhs, lrhs, rb.node, rlhs, rrhs)
|
||||
@ -89,7 +89,7 @@ impl<'a, 'tcx> DoubleComparisons {
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DoubleComparisons {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = expr.kind {
|
||||
self.check_binop(cx, kind.node, lhs, rhs, expr.span);
|
||||
Self::check_binop(cx, kind.node, lhs, rhs, expr.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,20 +32,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse {
|
||||
let map = cx.tcx.hir();
|
||||
// only check top level `use` statements
|
||||
for item in &m.item_ids {
|
||||
self.lint_item(cx, map.expect_item(item.id));
|
||||
lint_item(cx, map.expect_item(item.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EnumGlobUse {
|
||||
fn lint_item(self, cx: &LateContext<'_, '_>, item: &Item) {
|
||||
if item.vis.node.is_pub() {
|
||||
return; // re-exports are fine
|
||||
}
|
||||
if let ItemKind::Use(ref path, UseKind::Glob) = item.kind {
|
||||
if let Res::Def(DefKind::Enum, _) = path.res {
|
||||
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
|
||||
}
|
||||
fn lint_item(cx: &LateContext<'_, '_>, item: &Item) {
|
||||
if item.vis.node.is_pub() {
|
||||
return; // re-exports are fine
|
||||
}
|
||||
if let ItemKind::Use(ref path, UseKind::Glob) = item.kind {
|
||||
if let Res::Def(DefKind::Enum, _) = path.res {
|
||||
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision {
|
||||
if let ty::Float(fty) = ty.kind;
|
||||
if let hir::ExprKind::Lit(ref lit) = expr.kind;
|
||||
if let LitKind::Float(sym, _) | LitKind::FloatUnsuffixed(sym) = lit.node;
|
||||
if let Some(sugg) = self.check(sym, fty);
|
||||
if let Some(sugg) = Self::check(sym, fty);
|
||||
then {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
@ -63,7 +63,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision {
|
||||
impl ExcessivePrecision {
|
||||
// None if nothing to lint, Some(suggestion) if lint necessary
|
||||
#[must_use]
|
||||
fn check(self, sym: Symbol, fty: FloatTy) -> Option<String> {
|
||||
fn check(sym: Symbol, fty: FloatTy) -> Option<String> {
|
||||
let max = max_digits(fty);
|
||||
let sym_str = sym.as_str();
|
||||
if dot_zero_exclusion(&sym_str) {
|
||||
|
@ -222,7 +222,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
|
||||
}
|
||||
}
|
||||
|
||||
self.check_raw_ptr(cx, unsafety, decl, body, hir_id);
|
||||
Self::check_raw_ptr(cx, unsafety, decl, body, hir_id);
|
||||
self.check_line_number(cx, span, body);
|
||||
}
|
||||
|
||||
@ -282,7 +282,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
|
||||
}
|
||||
if let hir::TraitMethod::Provided(eid) = *eid {
|
||||
let body = cx.tcx.hir().body(eid);
|
||||
self.check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id);
|
||||
Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id);
|
||||
|
||||
if attr.is_none() && cx.access_levels.is_exported(item.hir_id) {
|
||||
check_must_use_candidate(
|
||||
@ -368,7 +368,6 @@ impl<'a, 'tcx> Functions {
|
||||
}
|
||||
|
||||
fn check_raw_ptr(
|
||||
self,
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
unsafety: hir::Unsafety,
|
||||
decl: &'tcx hir::FnDecl,
|
||||
|
@ -53,25 +53,25 @@ enum Side {
|
||||
|
||||
impl IntPlusOne {
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
fn check_lit(self, lit: &Lit, target_value: i128) -> bool {
|
||||
fn check_lit(lit: &Lit, target_value: i128) -> bool {
|
||||
if let LitKind::Int(value, ..) = lit.kind {
|
||||
return value == (target_value as u128);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn check_binop(self, cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<String> {
|
||||
fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<String> {
|
||||
match (binop, &lhs.kind, &rhs.kind) {
|
||||
// case where `x - 1 >= ...` or `-1 + x >= ...`
|
||||
(BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => {
|
||||
match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) {
|
||||
// `-1 + x`
|
||||
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if self.check_lit(lit, -1) => {
|
||||
self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS)
|
||||
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if Self::check_lit(lit, -1) => {
|
||||
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS)
|
||||
},
|
||||
// `x - 1`
|
||||
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => {
|
||||
self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS)
|
||||
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS)
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
@ -82,11 +82,11 @@ impl IntPlusOne {
|
||||
{
|
||||
match (&rhslhs.kind, &rhsrhs.kind) {
|
||||
// `y + 1` and `1 + y`
|
||||
(&ExprKind::Lit(ref lit), _) if self.check_lit(lit, 1) => {
|
||||
self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS)
|
||||
(&ExprKind::Lit(ref lit), _) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS)
|
||||
},
|
||||
(_, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => {
|
||||
self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS)
|
||||
(_, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS)
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
@ -97,11 +97,11 @@ impl IntPlusOne {
|
||||
{
|
||||
match (&lhslhs.kind, &lhsrhs.kind) {
|
||||
// `1 + x` and `x + 1`
|
||||
(&ExprKind::Lit(ref lit), _) if self.check_lit(lit, 1) => {
|
||||
self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS)
|
||||
(&ExprKind::Lit(ref lit), _) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS)
|
||||
},
|
||||
(_, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => {
|
||||
self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS)
|
||||
(_, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS)
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
@ -110,12 +110,12 @@ impl IntPlusOne {
|
||||
(BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => {
|
||||
match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
|
||||
// `-1 + y`
|
||||
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if self.check_lit(lit, -1) => {
|
||||
self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS)
|
||||
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if Self::check_lit(lit, -1) => {
|
||||
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS)
|
||||
},
|
||||
// `y - 1`
|
||||
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if self.check_lit(lit, 1) => {
|
||||
self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS)
|
||||
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS)
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
@ -125,7 +125,6 @@ impl IntPlusOne {
|
||||
}
|
||||
|
||||
fn generate_recommendation(
|
||||
self,
|
||||
cx: &EarlyContext<'_>,
|
||||
binop: BinOpKind,
|
||||
node: &Expr,
|
||||
@ -149,7 +148,7 @@ impl IntPlusOne {
|
||||
None
|
||||
}
|
||||
|
||||
fn emit_warning(self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) {
|
||||
fn emit_warning(cx: &EarlyContext<'_>, block: &Expr, recommendation: String) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
INT_PLUS_ONE,
|
||||
@ -170,8 +169,8 @@ impl IntPlusOne {
|
||||
impl EarlyLintPass for IntPlusOne {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
|
||||
if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.kind {
|
||||
if let Some(ref rec) = self.check_binop(cx, kind.node, lhs, rhs) {
|
||||
self.emit_warning(cx, item, rec.clone());
|
||||
if let Some(ref rec) = Self::check_binop(cx, kind.node, lhs, rhs) {
|
||||
Self::emit_warning(cx, item, rec.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -277,6 +277,7 @@ pub mod unicode;
|
||||
pub mod unsafe_removed_from_name;
|
||||
pub mod unused_io_amount;
|
||||
pub mod unused_label;
|
||||
pub mod unused_self;
|
||||
pub mod unwrap;
|
||||
pub mod use_self;
|
||||
pub mod vec;
|
||||
@ -606,6 +607,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con
|
||||
reg.register_late_lint_pass(box trait_bounds::TraitBounds);
|
||||
reg.register_late_lint_pass(box comparison_chain::ComparisonChain);
|
||||
reg.register_late_lint_pass(box mul_add::MulAddCheck);
|
||||
reg.register_late_lint_pass(box unused_self::UnusedSelf);
|
||||
|
||||
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
|
||||
arithmetic::FLOAT_ARITHMETIC,
|
||||
@ -683,6 +685,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con
|
||||
types::LINKEDLIST,
|
||||
unicode::NON_ASCII_LITERAL,
|
||||
unicode::UNICODE_NOT_NFC,
|
||||
unused_self::UNUSED_SELF,
|
||||
use_self::USE_SELF,
|
||||
]);
|
||||
|
||||
|
@ -350,13 +350,13 @@ impl EarlyLintPass for LiteralDigitGrouping {
|
||||
}
|
||||
|
||||
if let ExprKind::Lit(ref lit) = expr.kind {
|
||||
self.check_lit(cx, lit)
|
||||
Self::check_lit(cx, lit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LiteralDigitGrouping {
|
||||
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
|
||||
fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
|
||||
let in_macro = in_macro(lit.span);
|
||||
match lit.kind {
|
||||
LitKind::Int(..) => {
|
||||
|
@ -437,7 +437,7 @@ impl EarlyLintPass for MiscEarlyLints {
|
||||
);
|
||||
}
|
||||
},
|
||||
ExprKind::Lit(ref lit) => self.check_lit(cx, lit),
|
||||
ExprKind::Lit(ref lit) => Self::check_lit(cx, lit),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@ -469,7 +469,7 @@ impl EarlyLintPass for MiscEarlyLints {
|
||||
}
|
||||
|
||||
impl MiscEarlyLints {
|
||||
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
|
||||
fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
|
||||
// We test if first character in snippet is a number, because the snippet could be an expansion
|
||||
// from a built-in macro like `line!()` or a proc-macro like `#[wasm_bindgen]`.
|
||||
// Note that this check also covers special case that `line!()` is eagerly expanded by compiler.
|
||||
|
@ -117,7 +117,7 @@ impl Return {
|
||||
ast::ExprKind::Ret(ref inner) => {
|
||||
// allow `#[cfg(a)] return a; #[cfg(b)] return b;`
|
||||
if !expr.attrs.iter().any(attr_is_cfg) {
|
||||
self.emit_return_lint(
|
||||
Self::emit_return_lint(
|
||||
cx,
|
||||
span.expect("`else return` is not possible"),
|
||||
inner.as_ref().map(|i| i.span),
|
||||
@ -146,13 +146,7 @@ impl Return {
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_return_lint(
|
||||
&mut self,
|
||||
cx: &EarlyContext<'_>,
|
||||
ret_span: Span,
|
||||
inner_span: Option<Span>,
|
||||
replacement: RetReplacement,
|
||||
) {
|
||||
fn emit_return_lint(cx: &EarlyContext<'_>, ret_span: Span, inner_span: Option<Span>, replacement: RetReplacement) {
|
||||
match inner_span {
|
||||
Some(inner_span) => {
|
||||
if in_external_macro(cx.sess(), inner_span) || inner_span.from_expansion() {
|
||||
@ -191,7 +185,7 @@ impl Return {
|
||||
}
|
||||
|
||||
// Check for "let x = EXPR; x"
|
||||
fn check_let_return(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
|
||||
fn check_let_return(cx: &EarlyContext<'_>, block: &ast::Block) {
|
||||
let mut it = block.stmts.iter();
|
||||
|
||||
// we need both a let-binding stmt and an expr
|
||||
@ -275,7 +269,7 @@ impl EarlyLintPass for Return {
|
||||
}
|
||||
|
||||
fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
|
||||
self.check_let_return(cx, block);
|
||||
Self::check_let_return(cx, block);
|
||||
if_chain! {
|
||||
if let Some(ref stmt) = block.stmts.last();
|
||||
if let ast::StmtKind::Expr(ref expr) = stmt.kind;
|
||||
|
@ -244,7 +244,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
|
||||
|
||||
// Check that take is applied to `repeat(0)`
|
||||
if let Some(ref repeat_expr) = take_args.get(0);
|
||||
if self.is_repeat_zero(repeat_expr);
|
||||
if Self::is_repeat_zero(repeat_expr);
|
||||
|
||||
// Check that len expression is equals to `with_capacity` expression
|
||||
if let Some(ref len_arg) = take_args.get(1);
|
||||
@ -259,7 +259,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
/// Returns `true` if given expression is `repeat(0)`
|
||||
fn is_repeat_zero(&self, expr: &Expr) -> bool {
|
||||
fn is_repeat_zero(expr: &Expr) -> bool {
|
||||
if_chain! {
|
||||
if let ExprKind::Call(ref fn_expr, ref repeat_args) = expr.kind;
|
||||
if let ExprKind::Path(ref qpath_repeat) = fn_expr.kind;
|
||||
|
102
clippy_lints/src/unused_self.rs
Normal file
102
clippy_lints/src/unused_self.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use if_chain::if_chain;
|
||||
use rustc::hir::def::Res;
|
||||
use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
|
||||
use rustc::hir::{AssocItemKind, HirId, ImplItemKind, ImplItemRef, Item, ItemKind, Path};
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
use crate::utils::span_help_and_lint;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks methods that contain a `self` argument but don't use it
|
||||
///
|
||||
/// **Why is this bad?** It may be clearer to define the method as an associated function instead
|
||||
/// of an instance method if it doesn't require `self`.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust,ignore
|
||||
/// struct A;
|
||||
/// impl A {
|
||||
/// fn method(&self) {}
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Could be written:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// struct A;
|
||||
/// impl A {
|
||||
/// fn method() {}
|
||||
/// }
|
||||
/// ```
|
||||
pub UNUSED_SELF,
|
||||
pedantic,
|
||||
"methods that contain a `self` argument but don't use it"
|
||||
}
|
||||
|
||||
declare_lint_pass!(UnusedSelf => [UNUSED_SELF]);
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedSelf {
|
||||
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &Item) {
|
||||
if item.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
if let ItemKind::Impl(_, _, _, _, None, _, ref impl_item_refs) = item.kind {
|
||||
for impl_item_ref in impl_item_refs {
|
||||
if_chain! {
|
||||
if let ImplItemRef {
|
||||
kind: AssocItemKind::Method { has_self: true },
|
||||
..
|
||||
} = impl_item_ref;
|
||||
let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
|
||||
if let ImplItemKind::Method(_, body_id) = &impl_item.kind;
|
||||
then {
|
||||
let body = cx.tcx.hir().body(*body_id);
|
||||
let self_param = &body.params[0];
|
||||
let self_hir_id = self_param.pat.hir_id;
|
||||
let mut visitor = UnusedSelfVisitor {
|
||||
cx,
|
||||
uses_self: false,
|
||||
self_hir_id: &self_hir_id,
|
||||
};
|
||||
visitor.visit_body(body);
|
||||
if !visitor.uses_self {
|
||||
span_help_and_lint(
|
||||
cx,
|
||||
UNUSED_SELF,
|
||||
self_param.span,
|
||||
"unused `self` argument",
|
||||
"consider refactoring to a associated function",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
struct UnusedSelfVisitor<'a, 'tcx> {
|
||||
cx: &'a LateContext<'a, 'tcx>,
|
||||
uses_self: bool,
|
||||
self_hir_id: &'a HirId,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for UnusedSelfVisitor<'a, 'tcx> {
|
||||
fn visit_path(&mut self, path: &'tcx Path, _id: HirId) {
|
||||
if self.uses_self {
|
||||
// This function already uses `self`
|
||||
return;
|
||||
}
|
||||
if let Res::Local(hir_id) = &path.res {
|
||||
self.uses_self = self.self_hir_id == hir_id
|
||||
}
|
||||
walk_path(self, path);
|
||||
}
|
||||
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||
NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir())
|
||||
}
|
||||
}
|
@ -169,13 +169,13 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
|
||||
|
||||
fn eq_generic_arg(&mut self, left: &GenericArg, right: &GenericArg) -> bool {
|
||||
match (left, right) {
|
||||
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => self.eq_lifetime(l_lt, r_lt),
|
||||
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
|
||||
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn eq_lifetime(&mut self, left: &Lifetime, right: &Lifetime) -> bool {
|
||||
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
|
||||
left.name == right.name
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ pub use lint::Lint;
|
||||
pub use lint::LINT_LEVELS;
|
||||
|
||||
// begin lint list, do not remove this comment, it’s used in `update_lints`
|
||||
pub const ALL_LINTS: [Lint; 324] = [
|
||||
pub const ALL_LINTS: [Lint; 325] = [
|
||||
Lint {
|
||||
name: "absurd_extreme_comparisons",
|
||||
group: "correctness",
|
||||
@ -2086,6 +2086,13 @@ pub const ALL_LINTS: [Lint; 324] = [
|
||||
deprecation: None,
|
||||
module: "unused_label",
|
||||
},
|
||||
Lint {
|
||||
name: "unused_self",
|
||||
group: "pedantic",
|
||||
desc: "methods that contain a `self` argument but don\'t use it",
|
||||
deprecation: None,
|
||||
module: "unused_self",
|
||||
},
|
||||
Lint {
|
||||
name: "unused_unit",
|
||||
group: "style",
|
||||
|
@ -14,6 +14,7 @@
|
||||
clippy::use_self,
|
||||
clippy::useless_format,
|
||||
clippy::wrong_self_convention,
|
||||
clippy::unused_self,
|
||||
unused
|
||||
)]
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name
|
||||
--> $DIR/methods.rs:37:5
|
||||
--> $DIR/methods.rs:38:5
|
||||
|
|
||||
LL | / pub fn add(self, other: T) -> T {
|
||||
LL | | self
|
||||
@ -9,7 +9,7 @@ LL | | }
|
||||
= note: `-D clippy::should-implement-trait` implied by `-D warnings`
|
||||
|
||||
error: methods called `new` usually return `Self`
|
||||
--> $DIR/methods.rs:153:5
|
||||
--> $DIR/methods.rs:154:5
|
||||
|
|
||||
LL | / fn new() -> i32 {
|
||||
LL | | 0
|
||||
@ -19,7 +19,7 @@ LL | | }
|
||||
= note: `-D clippy::new-ret-no-self` implied by `-D warnings`
|
||||
|
||||
error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead
|
||||
--> $DIR/methods.rs:175:13
|
||||
--> $DIR/methods.rs:176:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
@ -31,7 +31,7 @@ LL | | .unwrap_or(0);
|
||||
= note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)`
|
||||
|
||||
error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead
|
||||
--> $DIR/methods.rs:179:13
|
||||
--> $DIR/methods.rs:180:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| {
|
||||
| _____________^
|
||||
@ -41,7 +41,7 @@ LL | | ).unwrap_or(0);
|
||||
| |____________________________^
|
||||
|
||||
error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead
|
||||
--> $DIR/methods.rs:183:13
|
||||
--> $DIR/methods.rs:184:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
@ -51,7 +51,7 @@ LL | | });
|
||||
| |__________________^
|
||||
|
||||
error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead
|
||||
--> $DIR/methods.rs:188:13
|
||||
--> $DIR/methods.rs:189:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -59,7 +59,7 @@ LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
|
||||
= note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))`
|
||||
|
||||
error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead
|
||||
--> $DIR/methods.rs:190:13
|
||||
--> $DIR/methods.rs:191:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| {
|
||||
| _____________^
|
||||
@ -69,7 +69,7 @@ LL | | ).unwrap_or(None);
|
||||
| |_____________________^
|
||||
|
||||
error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead
|
||||
--> $DIR/methods.rs:194:13
|
||||
--> $DIR/methods.rs:195:13
|
||||
|
|
||||
LL | let _ = opt
|
||||
| _____________^
|
||||
@ -80,7 +80,7 @@ LL | | .unwrap_or(None);
|
||||
= note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))`
|
||||
|
||||
error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead
|
||||
--> $DIR/methods.rs:205:13
|
||||
--> $DIR/methods.rs:206:13
|
||||
|
|
||||
LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -88,7 +88,7 @@ LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
|
||||
= note: replace `map(|p| format!("{}.", p)).unwrap_or(id)` with `map_or(id, |p| format!("{}.", p))`
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead
|
||||
--> $DIR/methods.rs:209:13
|
||||
--> $DIR/methods.rs:210:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
@ -100,7 +100,7 @@ LL | | .unwrap_or_else(|| 0);
|
||||
= note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)`
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead
|
||||
--> $DIR/methods.rs:213:13
|
||||
--> $DIR/methods.rs:214:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| {
|
||||
| _____________^
|
||||
@ -110,7 +110,7 @@ LL | | ).unwrap_or_else(|| 0);
|
||||
| |____________________________________^
|
||||
|
||||
error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead
|
||||
--> $DIR/methods.rs:217:13
|
||||
--> $DIR/methods.rs:218:13
|
||||
|
|
||||
LL | let _ = opt.map(|x| x + 1)
|
||||
| _____________^
|
||||
@ -120,7 +120,7 @@ LL | | );
|
||||
| |_________________^
|
||||
|
||||
error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
|
||||
--> $DIR/methods.rs:247:13
|
||||
--> $DIR/methods.rs:248:13
|
||||
|
|
||||
LL | let _ = v.iter().filter(|&x| *x < 0).next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -129,7 +129,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next();
|
||||
= note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)`
|
||||
|
||||
error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
|
||||
--> $DIR/methods.rs:250:13
|
||||
--> $DIR/methods.rs:251:13
|
||||
|
|
||||
LL | let _ = v.iter().filter(|&x| {
|
||||
| _____________^
|
||||
@ -139,7 +139,7 @@ LL | | ).next();
|
||||
| |___________________________^
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:267:22
|
||||
--> $DIR/methods.rs:268:22
|
||||
|
|
||||
LL | let _ = v.iter().find(|&x| *x < 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)`
|
||||
@ -147,25 +147,25 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some();
|
||||
= note: `-D clippy::search-is-some` implied by `-D warnings`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:268:20
|
||||
--> $DIR/methods.rs:269:20
|
||||
|
|
||||
LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:269:20
|
||||
--> $DIR/methods.rs:270:20
|
||||
|
|
||||
LL | let _ = (0..1).find(|x| *x == 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:270:22
|
||||
--> $DIR/methods.rs:271:22
|
||||
|
|
||||
LL | let _ = v.iter().find(|x| **x == 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:273:13
|
||||
--> $DIR/methods.rs:274:13
|
||||
|
|
||||
LL | let _ = v.iter().find(|&x| {
|
||||
| _____________^
|
||||
@ -175,13 +175,13 @@ LL | | ).is_some();
|
||||
| |______________________________^
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:279:22
|
||||
--> $DIR/methods.rs:280:22
|
||||
|
|
||||
LL | let _ = v.iter().position(|&x| x < 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:282:13
|
||||
--> $DIR/methods.rs:283:13
|
||||
|
|
||||
LL | let _ = v.iter().position(|&x| {
|
||||
| _____________^
|
||||
@ -191,13 +191,13 @@ LL | | ).is_some();
|
||||
| |______________________________^
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:288:22
|
||||
--> $DIR/methods.rs:289:22
|
||||
|
|
||||
LL | let _ = v.iter().rposition(|&x| x < 0).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
|
||||
|
||||
error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
|
||||
--> $DIR/methods.rs:291:13
|
||||
--> $DIR/methods.rs:292:13
|
||||
|
|
||||
LL | let _ = v.iter().rposition(|&x| {
|
||||
| _____________^
|
||||
@ -207,7 +207,7 @@ LL | | ).is_some();
|
||||
| |______________________________^
|
||||
|
||||
error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message
|
||||
--> $DIR/methods.rs:306:13
|
||||
--> $DIR/methods.rs:307:13
|
||||
|
|
||||
LL | let _ = opt.unwrap();
|
||||
| ^^^^^^^^^^^^
|
||||
|
111
tests/ui/unused_self.rs
Normal file
111
tests/ui/unused_self.rs
Normal file
@ -0,0 +1,111 @@
|
||||
#![warn(clippy::unused_self)]
|
||||
#![allow(clippy::boxed_local)]
|
||||
|
||||
mod unused_self {
|
||||
use std::pin::Pin;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
struct A {}
|
||||
|
||||
impl A {
|
||||
fn unused_self_move(self) {}
|
||||
fn unused_self_ref(&self) {}
|
||||
fn unused_self_mut_ref(&mut self) {}
|
||||
fn unused_self_pin_ref(self: Pin<&Self>) {}
|
||||
fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {}
|
||||
fn unused_self_pin_nested(self: Pin<Arc<Self>>) {}
|
||||
fn unused_self_box(self: Box<Self>) {}
|
||||
fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 {
|
||||
x + y
|
||||
}
|
||||
fn unused_self_class_method(&self) {
|
||||
Self::static_method();
|
||||
}
|
||||
|
||||
fn static_method() {}
|
||||
}
|
||||
}
|
||||
|
||||
mod used_self {
|
||||
use std::pin::Pin;
|
||||
|
||||
struct A {
|
||||
x: u8,
|
||||
}
|
||||
|
||||
impl A {
|
||||
fn used_self_move(self) -> u8 {
|
||||
self.x
|
||||
}
|
||||
fn used_self_ref(&self) -> u8 {
|
||||
self.x
|
||||
}
|
||||
fn used_self_mut_ref(&mut self) {
|
||||
self.x += 1
|
||||
}
|
||||
fn used_self_pin_ref(self: Pin<&Self>) -> u8 {
|
||||
self.x
|
||||
}
|
||||
fn used_self_box(self: Box<Self>) -> u8 {
|
||||
self.x
|
||||
}
|
||||
fn used_self_with_other_unused_args(&self, x: u8, y: u8) -> u8 {
|
||||
self.x
|
||||
}
|
||||
fn used_in_nested_closure(&self) -> u8 {
|
||||
let mut a = || -> u8 { self.x };
|
||||
a()
|
||||
}
|
||||
|
||||
#[allow(clippy::collapsible_if)]
|
||||
fn used_self_method_nested_conditions(&self, a: bool, b: bool, c: bool, d: bool) {
|
||||
if a {
|
||||
if b {
|
||||
if c {
|
||||
if d {
|
||||
self.used_self_ref();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn foo(&self) -> u32 {
|
||||
let mut sum = 0u32;
|
||||
for i in 0..self.x {
|
||||
sum += i as u32;
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
fn bar(&mut self, x: u8) -> u32 {
|
||||
let mut y = 0u32;
|
||||
for i in 0..x {
|
||||
y += self.foo()
|
||||
}
|
||||
y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod not_applicable {
|
||||
use std::fmt;
|
||||
|
||||
struct A {}
|
||||
|
||||
impl fmt::Debug for A {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "A")
|
||||
}
|
||||
}
|
||||
|
||||
impl A {
|
||||
fn method(x: u8, y: u8) {}
|
||||
}
|
||||
|
||||
trait B {
|
||||
fn method(&self) {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
75
tests/ui/unused_self.stderr
Normal file
75
tests/ui/unused_self.stderr
Normal file
@ -0,0 +1,75 @@
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:11:29
|
||||
|
|
||||
LL | fn unused_self_move(self) {}
|
||||
| ^^^^
|
||||
|
|
||||
= note: `-D clippy::unused-self` implied by `-D warnings`
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:12:28
|
||||
|
|
||||
LL | fn unused_self_ref(&self) {}
|
||||
| ^^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:13:32
|
||||
|
|
||||
LL | fn unused_self_mut_ref(&mut self) {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:14:32
|
||||
|
|
||||
LL | fn unused_self_pin_ref(self: Pin<&Self>) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:15:36
|
||||
|
|
||||
LL | fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:16:35
|
||||
|
|
||||
LL | fn unused_self_pin_nested(self: Pin<Arc<Self>>) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:17:28
|
||||
|
|
||||
LL | fn unused_self_box(self: Box<Self>) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:18:40
|
||||
|
|
||||
LL | fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 {
|
||||
| ^^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:21:37
|
||||
|
|
||||
LL | fn unused_self_class_method(&self) {
|
||||
| ^^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user