Hello.
In short: Why this code doesn't compile? Is it a problem with lifetime specifiers in the reference
function, can it be fixed to make the code compile?
Long version, to explain the relationale behind the reference
function:
I have a mutable reference that I want to pass to a function, but I want to be able to use it later, after the function returns. Example:
fn foo(aref: &mut i32) {}
let mut a = 1;
let aref = &mut a;
foo(aref);
*aref = 2;
It's obviously possible with immutable references: an immutable reference can be copied to pass it by value into a function, leaving the original untouched.
I thought, since a mutable reference cannot be cloned/copied, if it passed by value into a function, then it won't be accesible anymore in the original scope. But it turns out passing mutable references into functions behaves similar to immutable references, so the code above works.
But I wanted to wrap the mutable reference into a wrapper type, to encapsulate the reference and provide additional methods. I wrapped the mutable reference into a wrapper, but the wrapper seems to lack the privileges of mutable references; when it is passed by value into a function, it's gone in the parent scope and cannot be used anymore (unless the function returns it back, but that's not what I want). Example:
struct Parent<'a>(&'a mut i32);
fn foo(aref: Parent<'_>) {}
let mut a = 1;
let aref = Parent(&mut a);
foo(aref);
*aref.0 = 2; // error[E0382]: use of moved value: `aref.0`
Clone
/Copy
cannot be implemented for a wrapper either because the contained mutable reference cannot be cloned.
Initially, I solved it by copying the wrapper "by hand", creating a new wrapper object referencing the mutable reference from the previous:
foo(Parent(aref.0)); // Parent(aref.0) instead of aref
*aref.0 = 2; // Works again
But that meant exposing the internals of the wrapper, making the contained mutable reference public, and I wanted to avoid that, so I thought I could create a reference
method that does exactly that "copy by hand": Parent(aref.0)
, but in a method of Parent
. I tried that, but it didn't work; the return value of reference
, even after leaving its scope, is still considered an active borrow. See the code in the beginning.