rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.34k stars 12.59k forks source link

Two-phase borrows don't allow mutably splitting an array based on its length #53723

Open shepmaster opened 6 years ago

shepmaster commented 6 years ago
#![feature(nll)]
fn main() {
    let mut x = [1, 2];
    x.split_at_mut(x.len() / 2);
}
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
 --> src/main.rs:4:20
  |
4 |     x.split_at_mut(x.len() / 2);
  |     ---------------^-----------
  |     |              |
  |     |              immutable borrow occurs here
  |     mutable borrow occurs here
  |     borrow later used here

1.30.0-nightly (2018-08-24 d41f21f11a249ad78990)

/cc @nikomatsakis @pnkfelix

nikomatsakis commented 6 years ago

Nominating for triage.

eddyb commented 6 years ago

This has to do with two-phase not affecting auto-slicing, if we pre-slice it works:

#![feature(nll)]
fn main() {
    let x = &mut [1, 2][..];
    x.split_at_mut(x.len() / 2);
}

Whereas the original example compiles & checks like this:

#![feature(nll)]
fn main() {
    let mut x = [1, 2];
    (&mut x as &mut [_]).split_at_mut((&mut x as &mut [_]).len() / 2);
}
nikomatsakis commented 6 years ago

@eddyb yes, that was my suspicion, though I realize now that there won't be an easy fix, since we need the auto-slicing to convert from [u32; 2] type to [u32]. (I was hoping that this was a result of adding some redundant &mut * that we could omit.)

nikomatsakis commented 6 years ago

I think this is likely a "won't fix" -- but we should accumulate examples where 2PB fails to live up to its promises (and I would count this among them).

pnkfelix commented 6 years ago

Seasoned Rust hackers are probably already aware of this, but here's another way to get the effect described by @eddyb which may be more in line typical code in the wild. (Namely, add a type annotation to force the auto-slice to occur earlier.)

#![feature(nll)]
fn main() {
    let x: &mut [u32] = &mut [1, 2];
    x.split_at_mut(x.len() / 2);
}
nikomatsakis commented 6 years ago

We discussed expanding two-phase borrows in our weekly meeting on Tuesday and ultimately settled on "not right now but maybe later", so I'm marking this as deferred.

pnkfelix commented 5 years ago

Re-triaging for #56754. NLL-complete. P-medium. CC #49434