13

I'm strugglin' with the borrow checker - wonder o' wonder.

While I found a solution by adding a block, I am curious if there are other ways to end a mutable borrow so the next statement can access a binding afterwards.

Here's what I did so far:

let mut canvas: Canvas = Canvas {
    width: 5,
    height: 5,
    array: vec!['x'; 5*5],
};

{
    let mut renderer: CanvasRenderer = CanvasRenderer::new(&mut canvas);

    renderer.render_point('x', 3, 3);
}

println!("The Value in the array is: {}", canvas.array[9]);

I wrap a block around the binding of a CanvasRenderer object and after mutating the canvas and the scope ends, the CanvasRenderer dies and my mutable borrowed canvas is available to be read or whatever.

This works - but now I'd like to see other solutions!

I heard about drop(stuff) but it did not work as I thought it should.

trent
  • 25,033
  • 7
  • 51
  • 90
xetra11
  • 7,671
  • 14
  • 84
  • 159

1 Answers1

22

There is no other way; using blocks is the way to do it. Before Rust 2018 (available in Rust 1.31) all borrows are lexical, that is, they always correspond to some lexical scope. The only scope which is larger than a single statement is that of a block, so blocks are your only tool to limit borrow scopes.

drop() would not work for two reasons: first, because it would require non-lexical scope which is not supported before Rust 2018, and second, it cannot be a general-purpose tool for managing borrows: for example, it wouldn't be able to end an immutable borrow simply because immutable references are Copy and can't be "dropped".

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296
  • "because immutable references are Copy" Are you sure that a immu ref is a copy? So if the value it refers to is changed the receiver of that immu ref wont notice or wouldnt print ie. the new value? Because it has the copied state not the reference to it? Or am I failing hard with my brain again? ;) – xetra11 Mar 03 '16 at 08:08
  • @xetra11, if you have an immutable reference, **there is no way** to change the data it points to, neither through this reference nor by any other means (except `unsafe`, of course). More concretely, if you have an immutable reference to some variable, you neither can take a mutable reference to the same variable or its internals nor you can modify this variable directly even if it is stored in a `mut` slot. This is one of the cornerstones of Rust ownership/borrowing concept, and this is what makes aliasing of immutable references safe. Also note that mutable references are not copyable. – Vladimir Matveev Mar 03 '16 at 08:36
  • Ah yea youre right. It says if there is one mutable borrow around you cannot have an immut ref to that value. In other words there will only exist mut refs or copys of values?! (unless not unsafe) – xetra11 Mar 03 '16 at 08:59
  • @xetra11: Whether a reference is `Copy` is orthogonal to whether the underlying data is `Copy`. Immutable references don't copy the underlying data, but the reference itself is copyable (`impl Copy for &T`) -- this why you can share immutable references. `&mut T` references on the other hand are not copyable. – Daniel Mar 03 '16 at 10:44
  • Ok I think i got it now. A mut ref is never copied because if it would be - two workers could mutate its state. An immu ref will copy the reference to the underlying data so many workers can read them but because of immutability never change them. – xetra11 Mar 03 '16 at 12:15