diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index fae7f189bfd..832f3b92fa9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2018,12 +2018,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { let tcx = self.infcx.tcx; let hir = tcx.hir(); + + let has_split_at_mut = |ty: Ty<'tcx>| { + let ty = ty.peel_refs(); + match ty.kind() { + ty::Array(..) | ty::Slice(..) => true, + ty::Adt(def, _) if tcx.get_diagnostic_item(sym::Vec) == Some(def.did()) => true, + _ if ty == tcx.types.str_ => true, + _ => false, + } + }; if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)]) | ( [ProjectionElem::Deref, ProjectionElem::Index(index1)], [ProjectionElem::Deref, ProjectionElem::Index(index2)], ) = (&place.projection[..], &borrowed_place.projection[..]) { + let decl1 = &self.body.local_decls[*index1]; + let decl2 = &self.body.local_decls[*index2]; + let mut note_default_suggestion = || { err.help( "consider using `.split_at_mut(position)` or similar method to obtain two \ @@ -2035,14 +2048,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); }; - let Some(index1) = self.find_expr(self.body.local_decls[*index1].source_info.span) - else { + let Some(index1) = self.find_expr(decl1.source_info.span) else { note_default_suggestion(); return; }; - let Some(index2) = self.find_expr(self.body.local_decls[*index2].source_info.span) - else { + let Some(index2) = self.find_expr(decl2.source_info.span) else { note_default_suggestion(); return; }; @@ -2102,16 +2113,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); return; } + let place_ty = PlaceRef::ty(&place.as_ref(), self.body, tcx).ty; + let borrowed_place_ty = PlaceRef::ty(&borrowed_place.as_ref(), self.body, tcx).ty; + if !has_split_at_mut(place_ty) && !has_split_at_mut(borrowed_place_ty) { + // Only mention `split_at_mut` on `Vec`, array and slices. + 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", - ); + err.help("use `.split_at_mut(position)` 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 44a9a6ac811..2e7a6778dbc 100644 --- a/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr @@ -17,8 +17,6 @@ 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 @@ -29,8 +27,6 @@ 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.stderr b/tests/ui/suggestions/suggest-split-at-mut.stderr index f7d04b1db01..1bae7dc475e 100644 --- a/tests/ui/suggestions/suggest-split-at-mut.stderr +++ b/tests/ui/suggestions/suggest-split-at-mut.stderr @@ -21,7 +21,7 @@ LL | let b = &mut foo[2..]; 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 + = help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices error: aborting due to 2 previous errors