From 4da55202050818d7bb2ac5d4eabdf8dd1a1b7ff9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 18 Dec 2021 15:26:16 +0100 Subject: [PATCH] Ensure that RETURN_SELF_NOT_MUST_USE is not emitted if the method already has a must_use attribute --- clippy_lints/src/return_self_not_must_use.rs | 4 +++- tests/ui/return_self_not_must_use.rs | 17 +++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/return_self_not_must_use.rs b/clippy_lints/src/return_self_not_must_use.rs index 1118da6c8cb..2ff7f6bbb38 100644 --- a/clippy_lints/src/return_self_not_must_use.rs +++ b/clippy_lints/src/return_self_not_must_use.rs @@ -5,7 +5,7 @@ use rustc_hir::{Body, FnDecl, HirId, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does @@ -86,6 +86,8 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse { // We are only interested in methods, not in functions or associated functions. if matches!(kind, FnKind::Method(_, _, _)); if let Some(fn_def) = cx.tcx.hir().opt_local_def_id(hir_id); + // We don't want to emit this lint if the `#[must_use]` attribute is already there. + if !cx.tcx.hir().attrs(hir_id).iter().any(|attr| attr.has_name(sym::must_use)); if let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id()); // We don't want this method to be te implementation of a trait because the // `#[must_use]` should be put on the trait definition directly. diff --git a/tests/ui/return_self_not_must_use.rs b/tests/ui/return_self_not_must_use.rs index bdf3f3d7995..2fa389dec0a 100644 --- a/tests/ui/return_self_not_must_use.rs +++ b/tests/ui/return_self_not_must_use.rs @@ -5,12 +5,12 @@ pub struct Bar; pub trait Whatever { fn what(&self) -> Self; - // There should be no warning here! + // There should be no warning here! (returns a reference) fn what2(&self) -> &Self; } impl Bar { - // There should be no warning here! + // There should be no warning here! (note taking a self argument) pub fn not_new() -> Self { Self } @@ -20,22 +20,27 @@ impl Bar { pub fn bar(self) -> Self { self } - // There should be no warning here! + // There should be no warning here! (private method) fn foo2(&self) -> Self { Self } - // There should be no warning here! + // There should be no warning here! (returns a reference) pub fn foo3(&self) -> &Self { self } + // There should be no warning here! (already a `must_use` attribute) + #[must_use] + pub fn foo4(&self) -> Self { + Self + } } impl Whatever for Bar { - // There should be no warning here! + // There should be no warning here! (comes from the trait) fn what(&self) -> Self { self.foo2() } - // There should be no warning here! + // There should be no warning here! (comes from the trait) fn what2(&self) -> &Self { self }