Skip to content

Commit 9f9f0aa

Browse files
committed
Mention split_at_mut when mixing mutability in indexing ops
Emit suggestion when encountering ```rust let a = &mut foo[0]; let b = &foo[1]; a.use_mut(); ```
1 parent dbaa4e2 commit 9f9f0aa

File tree

4 files changed

+106
-4
lines changed

4 files changed

+106
-4
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
15271527
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
15281528
) => {
15291529
first_borrow_desc = "mutable ";
1530-
self.cannot_reborrow_already_borrowed(
1530+
let mut err = self.cannot_reborrow_already_borrowed(
15311531
span,
15321532
&desc_place,
15331533
&msg_place,
@@ -1537,7 +1537,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
15371537
"mutable",
15381538
&msg_borrow,
15391539
None,
1540-
)
1540+
);
1541+
self.suggest_slice_method_if_applicable(
1542+
&mut err,
1543+
place,
1544+
issued_borrow.borrowed_place,
1545+
span,
1546+
issued_span,
1547+
);
1548+
err
15411549
}
15421550
(
15431551
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
@@ -1555,6 +1563,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
15551563
&msg_borrow,
15561564
None,
15571565
);
1566+
self.suggest_slice_method_if_applicable(
1567+
&mut err,
1568+
place,
1569+
issued_borrow.borrowed_place,
1570+
span,
1571+
issued_span,
1572+
);
15581573
self.suggest_binding_for_closure_capture_self(&mut err, &issued_spans);
15591574
self.suggest_using_closure_argument_instead_of_capture(
15601575
&mut err,

tests/ui/borrowck/borrowck-assign-comp-idx.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | p[0] = 5;
99
LL |
1010
LL | println!("{}", *q);
1111
| -- immutable borrow later used here
12+
|
13+
= help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices
1214

1315
error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
1416
--> $DIR/borrowck-assign-comp-idx.rs:27:9

tests/ui/suggestions/suggest-split-at-mut.rs

+32
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,38 @@ fn bar() {
1616
println!("{:?} {:?}", a, b);
1717
}
1818

19+
fn baz() {
20+
let mut foo = [1,2,3,4];
21+
let a = &foo[..2];
22+
let b = &mut foo[2..]; //~ ERROR cannot borrow `foo` as mutable because it is also borrowed as immutable
23+
b[0] = 6;
24+
println!("{:?} {:?}", a, b);
25+
}
26+
27+
fn qux() {
28+
let mut foo = [1,2,3,4];
29+
let a = &mut foo[..2];
30+
let b = &foo[2..]; //~ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable
31+
a[0] = 5;
32+
println!("{:?} {:?}", a, b);
33+
}
34+
35+
fn bad() {
36+
let mut foo = [1,2,3,4];
37+
let a = &foo[1];
38+
let b = &mut foo[2]; //~ ERROR cannot borrow `foo[_]` as mutable because it is also borrowed as immutable
39+
*b = 6;
40+
println!("{:?} {:?}", a, b);
41+
}
42+
43+
fn bat() {
44+
let mut foo = [1,2,3,4];
45+
let a = &mut foo[1];
46+
let b = &foo[2]; //~ ERROR cannot borrow `foo[_]` as immutable because it is also borrowed as mutable
47+
*a = 5;
48+
println!("{:?} {:?}", a, b);
49+
}
50+
1951
fn main() {
2052
foo();
2153
bar();

tests/ui/suggestions/suggest-split-at-mut.stderr

+55-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,59 @@ LL | a[0] = 5;
2323
|
2424
= help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices
2525

26-
error: aborting due to 2 previous errors
26+
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
27+
--> $DIR/suggest-split-at-mut.rs:22:18
28+
|
29+
LL | let a = &foo[..2];
30+
| --- immutable borrow occurs here
31+
LL | let b = &mut foo[2..];
32+
| ^^^ mutable borrow occurs here
33+
LL | b[0] = 6;
34+
LL | println!("{:?} {:?}", a, b);
35+
| - immutable borrow later used here
36+
|
37+
= help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices
38+
39+
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
40+
--> $DIR/suggest-split-at-mut.rs:30:14
41+
|
42+
LL | let a = &mut foo[..2];
43+
| --- mutable borrow occurs here
44+
LL | let b = &foo[2..];
45+
| ^^^ immutable borrow occurs here
46+
LL | a[0] = 5;
47+
| ---- mutable borrow later used here
48+
|
49+
= help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices
50+
51+
error[E0502]: cannot borrow `foo[_]` as mutable because it is also borrowed as immutable
52+
--> $DIR/suggest-split-at-mut.rs:38:13
53+
|
54+
LL | let a = &foo[1];
55+
| ------- immutable borrow occurs here
56+
LL | let b = &mut foo[2];
57+
| ^^^^^^^^^^^ mutable borrow occurs here
58+
LL | *b = 6;
59+
LL | println!("{:?} {:?}", a, b);
60+
| - immutable borrow later used here
61+
|
62+
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
63+
= help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices
64+
65+
error[E0502]: cannot borrow `foo[_]` as immutable because it is also borrowed as mutable
66+
--> $DIR/suggest-split-at-mut.rs:46:13
67+
|
68+
LL | let a = &mut foo[1];
69+
| ----------- mutable borrow occurs here
70+
LL | let b = &foo[2];
71+
| ^^^^^^^ immutable borrow occurs here
72+
LL | *a = 5;
73+
| ------ mutable borrow later used here
74+
|
75+
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
76+
= help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices
77+
78+
error: aborting due to 6 previous errors
2779

28-
For more information about this error, try `rustc --explain E0499`.
80+
Some errors have detailed explanations: E0499, E0502.
81+
For more information about an error, try `rustc --explain E0499`.

0 commit comments

Comments
 (0)