forked from rust-lang/rust
-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#8071 - GuillaumeGomez:method-must-use, r=xFre…
…dnet Add new lint to warn when #[must_use] attribute should be used on a method This lint is somewhat similar to https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate but also different: it emits a warning by default and only targets methods (so not functions nor associated functions). Someone suggested it to me after this tweet: https://twitter.com/m_ou_se/status/1466439813230477312 I think it would reduce the number of cases of API misuses quite a lot. What do you think? --- changelog: Added new [`return_self_not_must_use`] lint
- Loading branch information
Showing
20 changed files
with
237 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
use clippy_utils::{diagnostics::span_lint, must_use_attr, nth_arg, return_ty}; | ||
use rustc_hir::def_id::LocalDefId; | ||
use rustc_hir::intravisit::FnKind; | ||
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; | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// This lint warns when a method returning `Self` doesn't have the `#[must_use]` attribute. | ||
/// | ||
/// ### Why is this bad? | ||
/// It prevents to "forget" to use the newly created value. | ||
/// | ||
/// ### Limitations | ||
/// This lint is only applied on methods taking a `self` argument. It would be mostly noise | ||
/// if it was added on constructors for example. | ||
/// | ||
/// ### Example | ||
/// ```rust | ||
/// pub struct Bar; | ||
/// | ||
/// impl Bar { | ||
/// // Bad | ||
/// pub fn bar(&self) -> Self { | ||
/// Self | ||
/// } | ||
/// | ||
/// // Good | ||
/// #[must_use] | ||
/// pub fn foo(&self) -> Self { | ||
/// Self | ||
/// } | ||
/// } | ||
/// ``` | ||
#[clippy::version = "1.59.0"] | ||
pub RETURN_SELF_NOT_MUST_USE, | ||
suspicious, | ||
"missing `#[must_use]` annotation on a method returning `Self`" | ||
} | ||
|
||
declare_lint_pass!(ReturnSelfNotMustUse => [RETURN_SELF_NOT_MUST_USE]); | ||
|
||
fn check_method(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'tcx>, fn_def: LocalDefId, span: Span, hir_id: HirId) { | ||
if_chain! { | ||
// If it comes from an external macro, better ignore it. | ||
if !in_external_macro(cx.sess(), span); | ||
if decl.implicit_self.has_implicit_self(); | ||
// We only show this warning for public exported methods. | ||
if cx.access_levels.is_exported(fn_def); | ||
if cx.tcx.visibility(fn_def.to_def_id()).is_public(); | ||
// No need to warn if the attribute is already present. | ||
if must_use_attr(cx.tcx.hir().attrs(hir_id)).is_none(); | ||
let ret_ty = return_ty(cx, hir_id); | ||
let self_arg = nth_arg(cx, hir_id, 0); | ||
// If `Self` has the same type as the returned type, then we want to warn. | ||
// | ||
// For this check, we don't want to remove the reference on the returned type because if | ||
// there is one, we shouldn't emit a warning! | ||
if self_arg.peel_refs() == ret_ty; | ||
|
||
then { | ||
span_lint( | ||
cx, | ||
RETURN_SELF_NOT_MUST_USE, | ||
span, | ||
"missing `#[must_use]` attribute on a method returning `Self`", | ||
); | ||
} | ||
} | ||
} | ||
|
||
impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse { | ||
fn check_fn( | ||
&mut self, | ||
cx: &LateContext<'tcx>, | ||
kind: FnKind<'tcx>, | ||
decl: &'tcx FnDecl<'tcx>, | ||
_: &'tcx Body<'tcx>, | ||
span: Span, | ||
hir_id: HirId, | ||
) { | ||
if_chain! { | ||
// 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); | ||
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. | ||
if cx.tcx.trait_id_of_impl(impl_def).is_none(); | ||
|
||
then { | ||
check_method(cx, decl, fn_def, span, hir_id); | ||
} | ||
} | ||
} | ||
|
||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) { | ||
if let TraitItemKind::Fn(ref sig, _) = item.kind { | ||
check_method(cx, sig.decl, item.def_id, item.span, item.hir_id()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#![crate_type = "lib"] | ||
|
||
#[derive(Clone)] | ||
pub struct Bar; | ||
|
||
pub trait Whatever { | ||
fn what(&self) -> Self; | ||
// There should be no warning here! | ||
fn what2(&self) -> &Self; | ||
} | ||
|
||
impl Bar { | ||
// There should be no warning here! | ||
pub fn not_new() -> Self { | ||
Self | ||
} | ||
pub fn foo(&self) -> Self { | ||
Self | ||
} | ||
pub fn bar(self) -> Self { | ||
self | ||
} | ||
// There should be no warning here! | ||
fn foo2(&self) -> Self { | ||
Self | ||
} | ||
// There should be no warning here! | ||
pub fn foo3(&self) -> &Self { | ||
self | ||
} | ||
} | ||
|
||
impl Whatever for Bar { | ||
// There should be no warning here! | ||
fn what(&self) -> Self { | ||
self.foo2() | ||
} | ||
// There should be no warning here! | ||
fn what2(&self) -> &Self { | ||
self | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
error: missing `#[must_use]` attribute on a method returning `Self` | ||
--> $DIR/return_self_not_must_use.rs:7:5 | ||
| | ||
LL | fn what(&self) -> Self; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: `-D clippy::return-self-not-must-use` implied by `-D warnings` | ||
|
||
error: missing `#[must_use]` attribute on a method returning `Self` | ||
--> $DIR/return_self_not_must_use.rs:17:5 | ||
| | ||
LL | / pub fn foo(&self) -> Self { | ||
LL | | Self | ||
LL | | } | ||
| |_____^ | ||
|
||
error: missing `#[must_use]` attribute on a method returning `Self` | ||
--> $DIR/return_self_not_must_use.rs:20:5 | ||
| | ||
LL | / pub fn bar(self) -> Self { | ||
LL | | self | ||
LL | | } | ||
| |_____^ | ||
|
||
error: aborting due to 3 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.