diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 9a8927c102973..f8a6fafbe78ac 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3940,13 +3940,30 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(decl) = local_decl && decl.can_be_made_mutable() { + let is_for_loop = matches!( + decl.local_info(), + LocalInfo::User(BindingForm::Var(VarBindingForm { + opt_match_place: Some((_, match_span)), + .. + })) if matches!(match_span.desugaring_kind(), Some(DesugaringKind::ForLoop)) + ); + let message = if is_for_loop + && let Ok(binding_name) = + self.infcx.tcx.sess.source_map().span_to_snippet(decl.source_info.span) + { + format!("(mut {}) ", binding_name) + } else { + "mut ".to_string() + }; err.span_suggestion_verbose( decl.source_info.span.shrink_to_lo(), "consider making this binding mutable", - "mut ".to_string(), + message, Applicability::MachineApplicable, ); + if !from_arg + && !is_for_loop && matches!( decl.local_info(), LocalInfo::User(BindingForm::Var(VarBindingForm { 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..fc4f1e4eacb95 --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.rs @@ -0,0 +1,10 @@ +//! regression test for +//! Ensure the diagnostic suggests `for &(mut x) ...` (parenthesized) instead of `&mut x`. + +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..fa230134df555 --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.stderr @@ -0,0 +1,16 @@ +error[E0384]: cannot assign twice to immutable variable `num` + --> $DIR/borrowck-for-loop-deref-pattern-assignment.rs:7: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 { + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0384`.