3

Why can't I pass data to a function when that function is not going to modify it and the ownership context doesn't end there?

This code gives an error:

let mut ar = [1, 2, 3, 4, 5];
let slice = &mut ar[1..=3];
slice[1] = 9;
println!("{:?} ", slice);
for e in ar.iter(){
    println!("{}", e)
}

This is the error:

error[E0502]: cannot borrow `ar` as immutable because it is also borrowed as mutable
 --> src/main.rs:6:14
  |
3 |     let slice = &mut ar[1..=3];
  |                      -- mutable borrow occurs here
...
6 |     for e in ar.iter() {
  |              ^^ immutable borrow occurs here
...
9 | }
  | - mutable borrow ends here

My guess is that we can't pass the array to the println! function because we have borrowed it, but I can't understand why. It's not like the println! function will change it!

I find the following behaviour difficult to understand. How can I print an array if I have slices of it?

This code works and prints [2, 9, 4]

let mut ar = [1, 2, 3, 4, 5];
let slice = &mut ar[1..=3];
slice[1] = 9;
println!("{:?} ", slice);

Also, this code works and prints everything properly, by modifying the slice we modify the original array!

let mut ar = [1, 2, 3, 4, 5];
{
    let slice = &mut ar[1..=3];
    slice[1] = 9;
    println!("{:?} ", slice); // -> [2, 9, 4]
}
for e in ar.iter(){
    println!("{}", e) //-> 1 2 9 4 5 as expected since the slice has changed
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
santi
  • 552
  • 8
  • 19
  • Yet another case that needs non lexical lifetimes. – Boiethios Oct 03 '18 at 11:26
  • I don't think it is a duplicate question, my question is why I can't print the array, asing for an explanation, not a solution to a problem, the problem is already solved in the last example. – santi Oct 03 '18 at 11:47
  • I don't understand you second duplication but I read about non lexical lifetimes and I am starting to understand the issue there... Basically the compiler is over-conservative :-) – santi Oct 03 '18 at 12:08
  • 1
    `println!` is a *macro*, not a *function*. – Shepmaster Oct 03 '18 at 12:34

1 Answers1

1

It seems you've already found the answer if your last example, but you still seem a little confused.

The println! here isn't the problem at all (note how the error message, which is actually very accurate here, doesn't mention it at all). The problem is that the slices variable is mutably borrowing from ar, and slices still exists when ar.iter() tries to borrow from ar. You can't have a mutable and immutable borrow at the same time, so the compiler stops you.

One solution, as you already found, is to ensure that the mutable slices borrow doesn't exist when you use ar.iter() (which borrows ar).


As for why the compiler is stopping you from doing this, it's because it doesn't want the value of an immutable borrow to unexpectedly change from under you. Basically, when you immutably borrow ar for ar.iter, it would be very strange if the underlying data suddenly changed. But since slice is already mutably borrowing the same data you could put some code in your loop that changes ar via slice, which would affect the iterator. The compiler doesn't want you doing this. The way it guarantees that you can't is by ensuring that no mutable borrow (slice in this case) exists when you make the immutable borrow. Right now, it doesn't check whether there is code that is actually trying to use the mutable borrow in the loop, it just guarantees that there couldn't possibly be.

JMAA
  • 1,730
  • 13
  • 24
  • That's pretty similar to what I understood, mainly for the last example. But println is not changing anything, I don't think any side effects could happen. If I don't iterate over the array, and just print it, the error is the same. – santi Oct 03 '18 at 11:55
  • You're correct, your original code can't do anything bad. But because the compiler isn't checking that you're not actually using `slice` in the loop, just that `slice` exists and therefore _could_ be used, it stops you. You just have to reassure the compiler by making sure `slice` doesn't exist when you make you make another borrow of `ar` – JMAA Oct 03 '18 at 12:05