-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Open
Labels
A-arrayArea: `[T; N]`Area: `[T; N]`A-borrow-checkerArea: The borrow checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`Area: Suggestions generated by the compiler applied by `cargo fix`C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.P-lowLow priorityLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
The following code is invalid due to lifetime rules:
fn main() {
let mut foo = [1,2,3,4];
let mut a = &mut foo[..2];
let mut b = &mut foo[2..];
a[0] = 5;
b[0] = 6;
println!("{:?} {:?}", a, b);
}
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> src/main.rs:4:22
|
3 | let mut a = &mut foo[..2];
| --- first mutable borrow occurs here
4 | let mut b = &mut foo[2..];
| ^^^ second mutable borrow occurs here
5 | a[0] = 5;
| ---- first borrow later used here
The solution is to either use unsafe
or (more appropriately) use split_at_mut
:
fn main() {
let mut foo = [1,2,3,4];
let (mut a, mut b) = foo.split_at_mut(2);
a[0] = 5;
b[0] = 6;
println!("{:?} {:?}", a, b);
}
The compiler should detect the case of multiple mutable borrows to the same array/slice and hint at the existence of split_at_mut
. Ideally, we would also verify wether there's a range overlap in order to explain to the user why what they want to do is problematic and disallowed in Rust.
The output should ideally be along the lines of the following (the structured suggestion is not needed to fix this issue, the text would be enough of an improvement):
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> src/main.rs:4:22
|
3 | let mut a = &mut foo[..2];
| --- first mutable borrow occurs here
4 | let mut b = &mut foo[2..];
| ^^^ second mutable borrow occurs here
5 | a[0] = 5;
| ---- first borrow later used here
= note: you cannot have multiple mutable borrows to the same piece of memory, as the compiler cannot assure that the different slices you're trying to use are non-overlapping
help: you can instead use `split_at_mut` to get two non-overlapping mutable slices from a single array/slice
|
3 | let (mut a, mut b) = foo.split_at_mut(2);
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
mxkmn and pastelmind
Metadata
Metadata
Assignees
Labels
A-arrayArea: `[T; N]`Area: `[T; N]`A-borrow-checkerArea: The borrow checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`Area: Suggestions generated by the compiler applied by `cargo fix`C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.P-lowLow priorityLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
unused_variables
andunused_assignments
lints do not catch array usage #65467split_at_mut
on multiple mutable index access #68819Rollup merge of rust-lang#68819 - estebank:split_at_mut, r=oli-obk
Detect borrow error involving sub-slices and suggest `split_at_mut`
split_at_mut
#124313Detect borrow error involving sub-slices and suggest `split_at_mut`
estebank commentedon Apr 25, 2024
After #124313, the only thing left to do would be to provide a structured suggestion, but in order to do so we'd need to have much more confidence that it can be properly applied and that the sub-slice indices do not match, and separately handle the sub-slicing case
from the sub-indexing case
Rollup merge of rust-lang#124313 - estebank:split-at-mut, r=fee1-dead
Unrolled build for rust-lang#124313