58

I'm trying to convert a mutable vector to an immutable vector in Rust. I thought this would work but it doesn't:

let data = &mut vec![];
let x = data;          // I thought x would now be an immutable reference

How can I turn a mutable reference into an immutable binding?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
jbrown
  • 7,518
  • 16
  • 69
  • 117
  • This is helpful... for eg. consider the 'partial_shuffle' function in rand crate, it takes in a mutable reference,... that's okay since it has to shuffle in place... But it returns mutable slices too... this thing got me for 2 days, the compiler kept complaining I wasn't able to use the original reference, since it said "can't have a immutable reference since already borrowed as an mutable".... but I couldn't find where I did that, since dataset.partial_shuffle() should be the only one and that mutable borrow must have ended with the function end. Continued... – AdityaG15 Oct 02 '21 at 19:05
  • ... Back to the first line "it takes in a mutable reference,... that's okay since it has to shuffle in place... But it returns mutable slices too", I didn't focus on that, so in such cases, where I don't need the returned random slices to be mutable now, I can just convert them to immutables... Takeaway from this: While reading docs, in rust, focus on the return type : ) – AdityaG15 Oct 02 '21 at 19:07

2 Answers2

68

Dereference then re-reference the value:

fn main() {
    let data = &mut vec![1, 2, 3];
    let x = &*data;
}

For what your code was doing, you should probably read What's the difference in `mut` before a variable name and after the `:`?. Your variable data is already immutable, but it contains a mutable reference. You cannot re-assign data, but you can change the pointed-to value.

How can I turn a mutable reference into an immutable binding?

It already is an immutable binding, as you cannot change what data is.

Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Hmm this code is in a function that returns `Vec`. If I return `&*data` I get an error `expected struct `std::vec::Vec`, found reference`. If I return `*data* I get an error `cannot move out of borrowed content`. Is that something else about the borrow checker? The way I've resolved this is to return `data.clone()` but I was trying to make it more performant, but I think I the borrow checker might not allow that since I'm creating the vector in the function. Maybe I phrased my question wrong, but how can I get a `Vec` from `data`? – jbrown Dec 28 '16 at 18:50
  • 1
    @jbrown Sounds like you are saying you want `let mut data = vec![1, 2, 3]; return data;`. – Shepmaster Dec 28 '16 at 19:01
  • yes, that's what I was looking for. Thanks. I'll re-read the rust docs about mutability – jbrown Dec 28 '16 at 19:25
7

The other solution that works now is to specify the type of x:

fn main() {
    let data = &mut vec![1, 2, 3];
    let x: &_ = data;
    println!("{x:?}");
    // This will fail as x immutable
    // *x = vec![]
}

When you don't specify the type, the compiler assumes you want the same type, which happens to be a &mut Vec<_>.

Penguin Brian
  • 1,991
  • 14
  • 25