Skip to content

Commit 3e218d1

Browse files
authored
fix(unnecessary_mut_passed): retain parens around the arguments (#15731)
Fixes #15722 changelog: [`unnecessary_mut_passed`]: retain parens around the arguments
2 parents 65f4098 + 9cb82d7 commit 3e218d1

File tree

7 files changed

+288
-88
lines changed

7 files changed

+288
-88
lines changed

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,6 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
533533
crate::multiple_unsafe_ops_per_block::MULTIPLE_UNSAFE_OPS_PER_BLOCK_INFO,
534534
crate::mut_key::MUTABLE_KEY_TYPE_INFO,
535535
crate::mut_mut::MUT_MUT_INFO,
536-
crate::mut_reference::UNNECESSARY_MUT_PASSED_INFO,
537536
crate::mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL_INFO,
538537
crate::mutex_atomic::MUTEX_ATOMIC_INFO,
539538
crate::mutex_atomic::MUTEX_INTEGER_INFO,
@@ -752,6 +751,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
752751
crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
753752
crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO,
754753
crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO,
754+
crate::unnecessary_mut_passed::UNNECESSARY_MUT_PASSED_INFO,
755755
crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
756756
crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
757757
crate::unnecessary_semicolon::UNNECESSARY_SEMICOLON_INFO,

clippy_lints/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@ mod multiple_bound_locations;
252252
mod multiple_unsafe_ops_per_block;
253253
mod mut_key;
254254
mod mut_mut;
255-
mod mut_reference;
256255
mod mutable_debug_assertion;
257256
mod mutex_atomic;
258257
mod needless_arbitrary_self_type;
@@ -375,6 +374,7 @@ mod unit_types;
375374
mod unnecessary_box_returns;
376375
mod unnecessary_literal_bound;
377376
mod unnecessary_map_on_constructor;
377+
mod unnecessary_mut_passed;
378378
mod unnecessary_owned_empty_strings;
379379
mod unnecessary_self_imports;
380380
mod unnecessary_semicolon;
@@ -483,7 +483,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
483483
store.register_late_pass(|_| Box::new(misc::LintPass));
484484
store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
485485
store.register_late_pass(|_| Box::new(mut_mut::MutMut));
486-
store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
486+
store.register_late_pass(|_| Box::new(unnecessary_mut_passed::UnnecessaryMutPassed));
487487
store.register_late_pass(|_| Box::<significant_drop_tightening::SignificantDropTightening<'_>>::default());
488488
store.register_late_pass(|_| Box::new(len_zero::LenZero));
489489
store.register_late_pass(move |_| Box::new(attrs::Attributes::new(conf)));

clippy_lints/src/mut_reference.rs renamed to clippy_lints/src/unnecessary_mut_passed.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::sugg::Sugg;
1+
use clippy_utils::diagnostics::span_lint_and_then;
2+
use clippy_utils::source::SpanRangeExt;
33
use rustc_errors::Applicability;
44
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
55
use rustc_lint::{LateContext, LateLintPass};
@@ -87,16 +87,33 @@ fn check_arguments<'tcx>(
8787
if let ty::Ref(_, _, Mutability::Not) | ty::RawPtr(_, Mutability::Not) = parameter.kind()
8888
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, arg) = argument.kind
8989
{
90-
let mut applicability = Applicability::MachineApplicable;
91-
let sugg = Sugg::hir_with_applicability(cx, arg, "_", &mut applicability).addr();
92-
span_lint_and_sugg(
90+
let applicability = Applicability::MachineApplicable;
91+
92+
let span_to_remove = {
93+
let span_until_arg = argument.span.until(arg.span);
94+
if let Some(Some(ref_pos)) = span_until_arg.with_source_text(cx, |src| {
95+
src
96+
// we don't use `strip_prefix` here, because `argument` might be enclosed in parens, in
97+
// which case `&` is no longer the prefix
98+
.find('&')
99+
// just a sanity check, in case some proc-macro messes up the spans
100+
.filter(|ref_pos| src[*ref_pos..].contains("mut"))
101+
}) && let Ok(lo) = u32::try_from(ref_pos + '&'.len_utf8())
102+
{
103+
span_until_arg.split_at(lo).1
104+
} else {
105+
return;
106+
}
107+
};
108+
109+
span_lint_and_then(
93110
cx,
94111
UNNECESSARY_MUT_PASSED,
95112
argument.span,
96113
format!("the {fn_kind} `{name}` doesn't need a mutable reference"),
97-
"remove this `mut`",
98-
sugg.to_string(),
99-
applicability,
114+
|diag| {
115+
diag.span_suggestion_verbose(span_to_remove, "remove this `mut`", String::new(), applicability);
116+
},
100117
);
101118
}
102119
}

tests/ui/mut_reference.stderr

Lines changed: 0 additions & 77 deletions
This file was deleted.

tests/ui/mut_reference.fixed renamed to tests/ui/unnecessary_mut_passed.fixed

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ mod issue11268 {
4040
struct MyStruct;
4141

4242
impl MyStruct {
43+
fn takes_nothing(&self) {}
4344
fn takes_ref(&self, a: &i32) {}
4445
fn takes_refmut(&self, a: &mut i32) {}
4546
fn takes_ref_ref(&self, a: &&i32) {}
@@ -168,3 +169,22 @@ fn raw_ptrs(my_struct: MyStruct) {
168169
my_struct.takes_raw_mut(&raw mut n);
169170
my_struct.takes_raw_const(a);
170171
}
172+
173+
#[expect(clippy::needless_borrow)]
174+
fn issue15722(mut my_struct: MyStruct) {
175+
(&my_struct).takes_nothing();
176+
//~^ unnecessary_mut_passed
177+
(&my_struct).takes_nothing();
178+
179+
// Only put parens around the argument that used to have it
180+
(&my_struct).takes_ref(&42);
181+
//~^ unnecessary_mut_passed
182+
//~| unnecessary_mut_passed
183+
#[expect(clippy::double_parens)]
184+
(&my_struct).takes_ref((&42));
185+
//~^ unnecessary_mut_passed
186+
//~| unnecessary_mut_passed
187+
#[expect(clippy::double_parens)]
188+
my_struct.takes_ref((&42));
189+
//~^ unnecessary_mut_passed
190+
}

tests/ui/mut_reference.rs renamed to tests/ui/unnecessary_mut_passed.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ mod issue11268 {
4040
struct MyStruct;
4141

4242
impl MyStruct {
43+
fn takes_nothing(&self) {}
4344
fn takes_ref(&self, a: &i32) {}
4445
fn takes_refmut(&self, a: &mut i32) {}
4546
fn takes_ref_ref(&self, a: &&i32) {}
@@ -168,3 +169,22 @@ fn raw_ptrs(my_struct: MyStruct) {
168169
my_struct.takes_raw_mut(&raw mut n);
169170
my_struct.takes_raw_const(a);
170171
}
172+
173+
#[expect(clippy::needless_borrow)]
174+
fn issue15722(mut my_struct: MyStruct) {
175+
(&mut my_struct).takes_nothing();
176+
//~^ unnecessary_mut_passed
177+
(&my_struct).takes_nothing();
178+
179+
// Only put parens around the argument that used to have it
180+
(&mut my_struct).takes_ref(&mut 42);
181+
//~^ unnecessary_mut_passed
182+
//~| unnecessary_mut_passed
183+
#[expect(clippy::double_parens)]
184+
(&mut my_struct).takes_ref((&mut 42));
185+
//~^ unnecessary_mut_passed
186+
//~| unnecessary_mut_passed
187+
#[expect(clippy::double_parens)]
188+
my_struct.takes_ref((&mut 42));
189+
//~^ unnecessary_mut_passed
190+
}

0 commit comments

Comments
 (0)