From b177b898bee7796a34fb29144ad1d4e132e7f41f Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 8 Aug 2025 10:08:35 +0200 Subject: [PATCH] `unnecessary_mut_passed`: add structured suggestion --- clippy_lints/src/mut_reference.rs | 13 +++++-- tests/ui/mut_reference.fixed | 59 +++++++++++++++++++++++++++++++ tests/ui/mut_reference.rs | 1 - tests/ui/mut_reference.stderr | 12 +++---- 4 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 tests/ui/mut_reference.fixed diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 31f51b457540..3b9c53cb3390 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,4 +1,6 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; @@ -83,13 +85,18 @@ fn check_arguments<'tcx>( let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); for (argument, parameter) in iter::zip(arguments, parameters) { if let ty::Ref(_, _, Mutability::Not) | ty::RawPtr(_, Mutability::Not) = parameter.kind() - && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _) = argument.kind + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, arg) = argument.kind { - span_lint( + let mut applicability = Applicability::MachineApplicable; + let sugg = Sugg::hir_with_applicability(cx, arg, "_", &mut applicability).addr(); + span_lint_and_sugg( cx, UNNECESSARY_MUT_PASSED, argument.span, format!("the {fn_kind} `{name}` doesn't need a mutable reference"), + "remove the `mut`", + sugg.to_string(), + applicability, ); } } diff --git a/tests/ui/mut_reference.fixed b/tests/ui/mut_reference.fixed new file mode 100644 index 000000000000..44baeef49a36 --- /dev/null +++ b/tests/ui/mut_reference.fixed @@ -0,0 +1,59 @@ +#![allow(unused_variables, dead_code)] +fn takes_an_immutable_reference(a: &i32) {} +fn takes_a_mutable_reference(a: &mut i32) {} + +mod issue11268 { + macro_rules! x { + ($f:expr) => { + $f(&mut 1); + }; + } + + fn f() { + x!(super::takes_an_immutable_reference); + x!(super::takes_a_mutable_reference); + } +} + +struct MyStruct; + +impl MyStruct { + fn takes_an_immutable_reference(&self, a: &i32) {} + + fn takes_a_mutable_reference(&self, a: &mut i32) {} +} + +#[warn(clippy::unnecessary_mut_passed)] +fn main() { + // Functions + takes_an_immutable_reference(&42); + //~^ unnecessary_mut_passed + + let as_ptr: fn(&i32) = takes_an_immutable_reference; + as_ptr(&42); + //~^ unnecessary_mut_passed + + // Methods + let my_struct = MyStruct; + my_struct.takes_an_immutable_reference(&42); + //~^ unnecessary_mut_passed + + // No error + + // Functions + takes_an_immutable_reference(&42); + let as_ptr: fn(&i32) = takes_an_immutable_reference; + as_ptr(&42); + + takes_a_mutable_reference(&mut 42); + let as_ptr: fn(&mut i32) = takes_a_mutable_reference; + as_ptr(&mut 42); + + let a = &mut 42; + takes_an_immutable_reference(a); + + // Methods + my_struct.takes_an_immutable_reference(&42); + my_struct.takes_a_mutable_reference(&mut 42); + my_struct.takes_an_immutable_reference(a); +} diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index f664c373cdc3..0dbf54300834 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -1,5 +1,4 @@ #![allow(unused_variables, dead_code)] -//@no-rustfix fn takes_an_immutable_reference(a: &i32) {} fn takes_a_mutable_reference(a: &mut i32) {} diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index 474221329c25..f4a1c1458e72 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -1,23 +1,23 @@ error: the function `takes_an_immutable_reference` doesn't need a mutable reference - --> tests/ui/mut_reference.rs:30:34 + --> tests/ui/mut_reference.rs:29:34 | LL | takes_an_immutable_reference(&mut 42); - | ^^^^^^^ + | ^^^^^^^ help: remove the `mut`: `&42` | = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_mut_passed)]` error: the function `as_ptr` doesn't need a mutable reference - --> tests/ui/mut_reference.rs:34:12 + --> tests/ui/mut_reference.rs:33:12 | LL | as_ptr(&mut 42); - | ^^^^^^^ + | ^^^^^^^ help: remove the `mut`: `&42` error: the method `takes_an_immutable_reference` doesn't need a mutable reference - --> tests/ui/mut_reference.rs:39:44 + --> tests/ui/mut_reference.rs:38:44 | LL | my_struct.takes_an_immutable_reference(&mut 42); - | ^^^^^^^ + | ^^^^^^^ help: remove the `mut`: `&42` error: aborting due to 3 previous errors