]> git.lizzy.rs Git - rust.git/commitdiff
Suggest `split_at_mut` on multiple mutable index access
authorEsteban Küber <esteban@kuber.com.ar>
Tue, 4 Feb 2020 01:58:28 +0000 (17:58 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Tue, 4 Feb 2020 02:00:14 +0000 (18:00 -0800)
src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
src/test/ui/suggestions/suggest-split-at-mut.rs [new file with mode: 0644]
src/test/ui/suggestions/suggest-split-at-mut.stderr [new file with mode: 0644]

index a8e534a9f650cadb8badad5a1cee559164fbfe59..67254cd0c48420ee75dc18e9223a97605427a432 100644 (file)
@@ -395,14 +395,20 @@ pub(in crate::borrow_check) fn report_conflicting_borrow(
 
             (BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => {
                 first_borrow_desc = "first ";
-                self.cannot_mutably_borrow_multiply(
+                let mut err = self.cannot_mutably_borrow_multiply(
                     span,
                     &desc_place,
                     &msg_place,
                     issued_span,
                     &msg_borrow,
                     None,
-                )
+                );
+                self.suggest_split_at_mut_if_applicable(
+                    &mut err,
+                    &place,
+                    &issued_borrow.borrowed_place,
+                );
+                err
             }
 
             (BorrowKind::Unique, BorrowKind::Unique) => {
@@ -547,6 +553,23 @@ pub(in crate::borrow_check) fn report_conflicting_borrow(
         err
     }
 
+    fn suggest_split_at_mut_if_applicable(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        place: &Place<'tcx>,
+        borrowed_place: &Place<'tcx>,
+    ) {
+        match (&place.projection[..], &borrowed_place.projection[..]) {
+            ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) => {
+                err.help(
+                    "consider using `.split_at_mut(position)` or similar method to obtain \
+                     two mutable non-overlapping sub-slices",
+                );
+            }
+            _ => {}
+        }
+    }
+
     /// Returns the description of the root place for a conflicting borrow and the full
     /// descriptions of the places that caused the conflict.
     ///
diff --git a/src/test/ui/suggestions/suggest-split-at-mut.rs b/src/test/ui/suggestions/suggest-split-at-mut.rs
new file mode 100644 (file)
index 0000000..d294c20
--- /dev/null
@@ -0,0 +1,8 @@
+fn main() {
+    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
+    *a = 5;
+    *b = 6;
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/suggestions/suggest-split-at-mut.stderr b/src/test/ui/suggestions/suggest-split-at-mut.stderr
new file mode 100644 (file)
index 0000000..330f012
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `foo[_]` as mutable more than once at a time
+  --> $DIR/suggest-split-at-mut.rs:4:13
+   |
+LL |     let a = &mut foo[2];
+   |             ----------- first mutable borrow occurs here
+LL |     let b = &mut foo[3];
+   |             ^^^^^^^^^^^ second mutable borrow occurs here
+LL |     *a = 5;
+   |     ------ first borrow later used here
+   |
+   = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.