From 12deedfe2ad865c2af3d61bbe98e06503640255a Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Thu, 20 Nov 2025 02:06:38 +0900 Subject: [PATCH] Improve mutable-binding suggestion to include name --- .../src/diagnostics/conflict_errors.rs | 29 +++++++++++++++---- ...rowck-for-loop-deref-pattern-assignment.rs | 7 +++++ ...k-for-loop-deref-pattern-assignment.stderr | 20 +++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.rs create mode 100644 tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 9a8927c102973..d3ed77ca62735 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3940,12 +3940,29 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(decl) = local_decl && decl.can_be_made_mutable() { - err.span_suggestion_verbose( - decl.source_info.span.shrink_to_lo(), - "consider making this binding mutable", - "mut ".to_string(), - Applicability::MachineApplicable, - ); + if matches!( + decl.local_info(), + LocalInfo::User(BindingForm::Var(VarBindingForm { + opt_match_place: Some((Some(_), _)), + .. + })) + ) && let Ok(binding_name) = + self.infcx.tcx.sess.source_map().span_to_snippet(decl.source_info.span) + { + err.span_suggestion_verbose( + decl.source_info.span.shrink_to_lo(), + "consider making this binding mutable", + format!("(mut {}) ", binding_name), + Applicability::MachineApplicable, + ); + } else { + err.span_suggestion_verbose( + decl.source_info.span.shrink_to_lo(), + "consider making this binding mutable", + "mut ".to_string(), + Applicability::MachineApplicable, + ); + } if !from_arg && matches!( decl.local_info(), diff --git a/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.rs b/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.rs new file mode 100644 index 0000000000000..c69aa3a2bf0e9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.rs @@ -0,0 +1,7 @@ +fn main() { + let nums: &[u32] = &[1, 2, 3]; + for &num in nums { + num *= 2; //~ ERROR cannot assign twice to immutable variable `num` + println!("{num}"); + } +} diff --git a/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.stderr b/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.stderr new file mode 100644 index 0000000000000..e906e8332850d --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.stderr @@ -0,0 +1,20 @@ +error[E0384]: cannot assign twice to immutable variable `num` + --> $DIR/borrowck-for-loop-deref-pattern-assignment.rs:4:9 + | +LL | for &num in nums { + | --- first assignment to `num` +LL | num *= 2; + | ^^^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | for &(mut num) num in nums { + | +++++++++ +help: to modify the original value, take a borrow instead + | +LL | for &ref mut num in nums { + | +++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0384`.