Skip to content

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

Closed
@grantslatton

Description

@grantslatton

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

Activity

jonas-schievink

jonas-schievink commented on Nov 25, 2017

@jonas-schievink
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

jonas-schievink commented on Nov 25, 2017

@jonas-schievink
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

grantslatton commented on Nov 25, 2017

@grantslatton
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

grantslatton commented on Nov 25, 2017

@grantslatton
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

bluss commented on Nov 25, 2017

@bluss
Member

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

jonas-schievink

jonas-schievink commented on Nov 25, 2017

@jonas-schievink
Contributor

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

bluss

bluss commented on Nov 25, 2017

@bluss
Member

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

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jonas-schievink@bluss@grantslatton

        Issue actions

          Compiler thinks variable needs to be mutable when getting an owned slice · Issue #46265 · rust-lang/rust