Skip to content

Suggest split_at_mut when trying to use multiple non-overlapping mutable slices to the same array #58792

@estebank

Description

@estebank
Contributor

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);
  |         ^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^

Activity

added
A-diagnosticsArea: Messages for errors, warnings, and lints
A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`
on Feb 27, 2019
added
D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Oct 8, 2019
added
C-enhancementCategory: An issue proposing an enhancement or a PR with one.
on Nov 19, 2019
added a commit that references this issue on Feb 4, 2020
793a5e6
estebank

estebank commented on Apr 25, 2024

@estebank
ContributorAuthor

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

    let (a, b) = foo.split_at_mut(2);
    a[0] = 5;
    b[0] = 6;
    println!("{:?} {:?}", a, b);

from the sub-indexing case

    let (a, b) = foo.split_at_mut(3);
    let a = &mut a[2];
    let b = &mut b[0];
    *a = 5;
    *b = 6;
    println!("{:?} {:?}", a, b);
added
P-lowLow priority
and removed
D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.
on Apr 25, 2024
added a commit that references this issue on Apr 25, 2024
added a commit that references this issue on Apr 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-arrayArea: `[T; N]`A-borrow-checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-enhancementCategory: An issue proposing an enhancement or a PR with one.P-lowLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @estebank@workingjubilee

        Issue actions

          Suggest `split_at_mut` when trying to use multiple non-overlapping mutable slices to the same array · Issue #58792 · rust-lang/rust