-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add needless_pass_by_ref_mut
lint
#10900
Conversation
r? @Jarcho (rustbot has picked a reviewer for you, use r? to override) |
I found two cases where it doesn't work: fn foo2(s: &mut Vec<u32>) {
s.push(8);
}
fn foo3(s: &mut Vec<u32>) -> &mut Vec<u32> {
s
} |
111f7ad
to
3a44760
Compare
I fixed the two cases. If people could please check if I didn't miss other cases? :) |
3a44760
to
4ee1c39
Compare
I found a couple after running https://github.com/dtolnay/anyhow/blob/1f17666ef1d4d3cd1f05a9ee5e79f75d66801c66/src/ptr.rs#LL151C1-L157C6 The first (anyhow) is really bad, as it's necessary for it to be sound. We should probably consider creation of Great work on this, though :) |
Thanks a lot for the cases! For |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this isn't done yet, but I thought I'd give a small review anyway ^^
Very much appreciated, thanks! I'll fix them when I resume this work tomorrow. |
I'd like to make sure these are also caught: impl Bar {
// Should warn about `vec`
pub fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
vec.len()
}
// Should warn about `vec`
pub fn badger(&mut self, vec: &mut Vec<i32>) -> usize {
vec.len()
}
} Additionally, shouldn't we warn about struct Foo {
x: i32
}
impl Foo {
pub fn get(&mut self) -> i32 {
self.x
}
} I have never worked in this repository before - how do I easily test a single lint like this? |
|
@emilk: I'll add them to the tests within this PR. The more I have, the better. |
This is tricky because you might want to actually force your object instance to be mutably borrowed even if you don't use it mutably internally. However, we can always add another lint ( |
fac1b21
to
317ac5b
Compare
@Centri3 I was able to fix two of the four problems you linked (the alias and the |
The easiest way is lintcheck; |
317ac5b
to
69041b6
Compare
needless_pass_by_ref
lintneedless_pass_by_ref_mut
lint
Thanks! That was quite useful and indeed, |
☔ The latest upstream changes (presumably #10934) made this pull request unmergeable. Please resolve the merge conflicts. |
6bb17f7
to
83d8728
Compare
From |
3bd0481
to
3c85849
Compare
Just realized that Just in case, here's the diff to have the From cdfb83030b2f78d672d9f6b08911cf8123edf338 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Mon, 3 Jul 2023 22:19:32 +0200
Subject: [PATCH] Make NEEDLESS_PASS_BY_REF_MUT not emitted if
`avoid-breaking-exported-api` option is enabled
---
clippy_lints/src/lib.rs | 6 ++++-
clippy_lints/src/needless_pass_by_ref_mut.rs | 22 +++++++++++++++++--
.../ui/should_impl_trait/method_list_2.stderr | 10 +--------
3 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index e1e4a83b0..040ed1a86 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -1058,7 +1058,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
let stack_size_threshold = conf.stack_size_threshold;
store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold)));
store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit));
- store.register_late_pass(|_| Box::new(needless_pass_by_ref_mut::NeedlessPassByRefMut));
+ store.register_late_pass(move |_| {
+ Box::new(needless_pass_by_ref_mut::NeedlessPassByRefMut::new(
+ avoid_breaking_exported_api,
+ ))
+ });
store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls));
store.register_late_pass(move |_| {
Box::new(single_call_fn::SingleCallFn {
diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs
index c5dc87cdf..614b1f965 100644
--- a/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -12,7 +12,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{self, Ty};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::kw;
use rustc_span::Span;
@@ -43,7 +43,21 @@ declare_clippy_lint! {
suspicious,
"using a `&mut` argument when it's not mutated"
}
-declare_lint_pass!(NeedlessPassByRefMut => [NEEDLESS_PASS_BY_REF_MUT]);
+
+#[derive(Copy, Clone)]
+pub struct NeedlessPassByRefMut {
+ avoid_breaking_exported_api: bool,
+}
+
+impl NeedlessPassByRefMut {
+ pub fn new(avoid_breaking_exported_api: bool) -> Self {
+ Self {
+ avoid_breaking_exported_api,
+ }
+ }
+}
+
+impl_lint_pass!(NeedlessPassByRefMut => [NEEDLESS_PASS_BY_REF_MUT]);
fn should_skip<'tcx>(
cx: &LateContext<'tcx>,
@@ -81,6 +95,10 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut {
span: Span,
fn_def_id: LocalDefId,
) {
+ if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(fn_def_id) {
+ return;
+ }
+
if span.from_expansion() {
return;
}
diff --git a/tests/ui/should_impl_trait/method_list_2.stderr b/tests/ui/should_impl_trait/method_list_2.stderr
index e47cb209b..10bfea68f 100644
--- a/tests/ui/should_impl_trait/method_list_2.stderr
+++ b/tests/ui/should_impl_trait/method_list_2.stderr
@@ -39,14 +39,6 @@ LL | | }
|
= help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
-error: this argument is a mutable reference, but not used mutably
- --> $DIR/method_list_2.rs:38:31
- |
-LL | pub fn hash(&self, state: &mut T) {
- | ^^^^^^ help: consider changing to: `&T`
- |
- = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
-
error: method `index` can be confused for the standard trait method `std::ops::Index::index`
--> $DIR/method_list_2.rs:42:5
|
@@ -157,5 +149,5 @@ LL | | }
|
= help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name
-error: aborting due to 16 previous errors
+error: aborting due to 15 previous errors
--
2.34.1 |
cdfb830
to
33adfcd
Compare
Why do you think avoiding API breakage by default is a bad idea? |
Probably because it doesn't cause API breakage, just a clippy lint. |
I just learned about Whether or not For consistency with how other lints work, it seems this lint should heed it too (just like similar lints do, e.g. |
I disagree as changing |
It's a good point, however: If you have |
Those are the cases where you should probably allow the lint, though it isn't particularly vocal about this unfortunately (something should be added to the description noting this) |
Would it be possible to shadow a trait method following the lint's suggestion? If so, it could break the build. |
That said, there is an argument to be made that we should make the default |
I disagree with this position: clippy is supposed to tell me what it potential issues it sees, and then it's up to me to decide whether or not I apply them. So something I can suggest is the following: if an item is publicly accessible, to not enable the possibility of automatically fixing it. What do you think about it? |
So I did the following changes:
|
Most likely so, but I wouldn't consider this a "breaking change"; afaik that would be up to the library author to refactor (which, since it now isn't machine applicable, wouldn't be a big deal), as the only way I can think of for that to happen is the usage within the function itself, which changing shouldn't cause issues downstream Perhaps something like |
The reason for the Sorry I'm being pedantic here, but we've had some bad experience with users ditching clippy because of too many false positives, and we want this to be useful. @bors r+ |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
…arth Fix typo in `needless_pass_by_ref_mut` lint description Someone nicely showed me that I made a small typo in #10900.
…arth Fix typo in `needless_pass_by_ref_mut` lint description Someone nicely showed me that I made a small typo in #10900.
…arth Fix typo in `needless_pass_by_ref_mut` lint description Someone nicely showed me that I made a small typo in #10900. changelog: none
changelog: [
needless_pass_by_ref_mut
]: This PR add a new lintneedless_pass_by_ref_mut
which emits a warning in case a&mut
function argument isn't used mutably. It doesn't warn on trait and trait impls functions.Fixes #8863.