diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 4878da530b0f5..6ab78bd03f84b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1544,6 +1544,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, place, issued_borrow.borrowed_place, + span, + issued_span, ); self.suggest_using_closure_argument_instead_of_capture( &mut err, @@ -1974,10 +1976,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err: &mut Diag<'_>, place: Place<'tcx>, borrowed_place: Place<'tcx>, + span: Span, + issued_span: Span, ) { let tcx = self.infcx.tcx; let hir = tcx.hir(); - if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)]) | ( [ProjectionElem::Deref, ProjectionElem::Index(index1)], @@ -1986,28 +1989,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { let mut note_default_suggestion = || { err.help( - "consider using `.split_at_mut(position)` or similar method to obtain \ - two mutable non-overlapping sub-slices", + "consider using `.split_at_mut(position)` or similar method to obtain two \ + mutable non-overlapping sub-slices", ) - .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices"); - }; - - let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { - note_default_suggestion(); - return; + .help( + "consider using `.swap(index_1, index_2)` to swap elements at the specified \ + indices", + ); }; - let mut expr_finder = - FindExprBySpan::new(self.body.local_decls[*index1].source_info.span); - expr_finder.visit_expr(hir.body(body_id).value); - let Some(index1) = expr_finder.result else { + let Some(index1) = self.find_expr(self.body.local_decls[*index1].source_info.span) + else { note_default_suggestion(); return; }; - expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span); - expr_finder.visit_expr(hir.body(body_id).value); - let Some(index2) = expr_finder.result else { + let Some(index2) = self.find_expr(self.body.local_decls[*index2].source_info.span) + else { note_default_suggestion(); return; }; @@ -2065,7 +2063,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { format!("{obj_str}.swap({index1_str}, {index2_str})"), Applicability::MachineApplicable, ); + return; } + let Some(index1) = self.find_expr(span) else { return }; + let hir::Node::Expr(parent) = tcx.parent_hir_node(index1.hir_id) else { return }; + let hir::ExprKind::Index(..) = parent.kind else { return }; + let Some(index2) = self.find_expr(issued_span) else { return }; + let hir::Node::Expr(parent) = tcx.parent_hir_node(index2.hir_id) else { return }; + let hir::ExprKind::Index(..) = parent.kind else { return }; + err.help( + "use `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping \ + sub-slices", + ); } /// Suggest using `while let` for call `next` on an iterator in a for loop. diff --git a/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr index 2e7a6778dbc30..44a9a6ac81146 100644 --- a/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr @@ -17,6 +17,8 @@ LL | let q = &mut f[&s]; | ^ second mutable borrow occurs here LL | p.use_mut(); | - first borrow later used here + | + = help: use `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices error[E0499]: cannot borrow `f.foo` as mutable more than once at a time --> $DIR/borrowck-overloaded-index-autoderef.rs:53:18 @@ -27,6 +29,8 @@ LL | let q = &mut f.foo[&s]; | ^^^^^ second mutable borrow occurs here LL | p.use_mut(); | - first borrow later used here + | + = help: use `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices error[E0502]: cannot borrow `f.foo` as mutable because it is also borrowed as immutable --> $DIR/borrowck-overloaded-index-autoderef.rs:65:18 diff --git a/tests/ui/suggestions/suggest-split-at-mut.rs b/tests/ui/suggestions/suggest-split-at-mut.rs index d294c20b8240e..a80d35b19515f 100644 --- a/tests/ui/suggestions/suggest-split-at-mut.rs +++ b/tests/ui/suggestions/suggest-split-at-mut.rs @@ -1,4 +1,4 @@ -fn main() { +fn foo() { let mut foo = [1, 2, 3, 4]; let a = &mut foo[2]; let b = &mut foo[3]; //~ ERROR cannot borrow `foo[_]` as mutable more than once at a time @@ -6,3 +6,17 @@ fn main() { *b = 6; println!("{:?} {:?}", a, b); } + +fn bar() { + let mut foo = [1,2,3,4]; + let a = &mut foo[..2]; + let b = &mut foo[2..]; //~ ERROR cannot borrow `foo` as mutable more than once at a time + a[0] = 5; + b[0] = 6; + println!("{:?} {:?}", a, b); +} + +fn main() { + foo(); + bar(); +} diff --git a/tests/ui/suggestions/suggest-split-at-mut.stderr b/tests/ui/suggestions/suggest-split-at-mut.stderr index c42f09e3201db..f7d04b1db01d6 100644 --- a/tests/ui/suggestions/suggest-split-at-mut.stderr +++ b/tests/ui/suggestions/suggest-split-at-mut.stderr @@ -11,6 +11,18 @@ LL | *a = 5; = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices = help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices -error: aborting due to 1 previous error +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/suggest-split-at-mut.rs:13:18 + | +LL | let a = &mut foo[..2]; + | --- first mutable borrow occurs here +LL | let b = &mut foo[2..]; + | ^^^ second mutable borrow occurs here +LL | a[0] = 5; + | ---- first borrow later used here + | + = help: use `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0499`.