Skip to content

Compiler thinks variable needs to be mutable when getting an owned slice #46265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
grantslatton opened this issue Nov 25, 2017 · 7 comments
Closed

Comments

@grantslatton
Copy link

https://play.rust-lang.org/?gist=be40620b431766ae921d89b3e2c0b9e5&version=nightly

fn main() {
    let vec_a: Vec<u32> = vec![];
    let mut vec_b: Vec<u32> = vec![];
    vec_b.append(&mut vec_a[..].to_owned());
}

error[E0596]: cannot borrow immutable local variable `vec_a` as mutable
 --> src/main.rs:4:23
  |
2 |     let vec_a: Vec<u32> = vec![];
  |         ----- consider changing this to `mut vec_a`
3 |     let mut vec_b: Vec<u32> = vec![];
4 |     vec_b.append(&mut vec_a[..].to_owned());
  |                       ^^^^^ cannot borrow mutably
@jonas-schievink
Copy link
Contributor

This is correct - you aren't getting an owned slice, you're getting a &mut [u32], a mutable slice. Since the data the slice points to is owned by vec_a, you can only mutably refer to it if you have a mutable reference to vec_a itself.

@jonas-schievink
Copy link
Contributor

You can also use &vec_a instead of &mut vec_a, since the mutability isn't needed here (only vec_b needs to be mutable, since you append to it).

@grantslatton
Copy link
Author

@jonas-schievink but as far as I know, I getting an immutable slice. &mut should apply to the Vec<u32> returned by to_owned. Additional parentheses to clarify this don't help:

https://play.rust-lang.org/?gist=266b22ca7d45c52200c068fa34bb5b61&version=nightly

fn main() {
    let vec_a: Vec<u32> = vec![];
    let mut vec_b: Vec<u32> = vec![];
    vec_b.append(&mut (vec_a[..].to_owned()));
}

In the above code, vec_a[..] should be a &[u32], right? And (vec_a[..].to_owned()) should be a Vec<u32>, right? Why can't I get a &mut of the owned Vec?

And why does splitting it into 2 lines work?

https://play.rust-lang.org/?gist=1600e7488b3de8e7ed489828af1c6727&version=nightly

fn main() {
    let vec_a: Vec<u32> = vec![];
    let mut vec_b: Vec<u32> = vec![];
    let mut owned = vec_a[..].to_owned();
    vec_b.append(&mut owned);
}

The above code compiles, but all I've done is introduce an intermediate variable owned.

@grantslatton
Copy link
Author

@jonas-schievink

You can also use &vec_a instead of &mut vec_a, since the mutability isn't needed here (only vec_b needs to be mutable, since you append to it).

appends type signature is fn append(&mut self, other: &mut Vec<T>)

See https://doc.rust-lang.org/std/vec/struct.Vec.html#method.append

@bluss
Copy link
Member

bluss commented Nov 25, 2017

The compiler is calling IndexMut here, and that's wrong. vec_a[..].to_vec() only needs Index

@jonas-schievink
Copy link
Contributor

Ah, right, that's an actual bug, of course: #28935

@bluss
Copy link
Member

bluss commented Nov 25, 2017

Thanks both! This is a duplicate of #28935 and it seems like an exact match.

@bluss bluss closed this as completed Nov 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants