Hi, I'm completely new to Rust (my background is C++), so maybe I'm missing some feuture that may help. In my toy project, I got into issue which essence is (hopefully) extracted in the snippet below.
I want to return an instance + instance referencing it from a function. Of course, the instance must be heap-allocated so that its address will not change after return. So I basically want to return a pair (Box<X>, XRef)
where lifetime of XRef
is limited by lifetime of X
stored inside Box<X>
– the problem is shown as g()
function.
It's rather academic question, I can get around with moving the problem down with f()
.
struct X {
value: i32,
}
struct XRef<'a> {
x: &'a X,
}
fn f<'a>(x: &'a X) -> XRef<'a> {
XRef { x }
}
// I want to return boxed X together with XRef pointing to it
// the lifetime of returned Box and XRef should be the same
// but I don't know how can I denote it
fn g<'a>() -> (Box<X>, XRef<'a>) {
let x = Box::new(X { value: 10 });
let xref = XRef { x: &x };
// this should be OK (altough a bit tricky),
// but I think compiler will not get it:
// the X instance is boxed inside x, so the address of it
// (pointed to by xref) will not change
// but compiler will complain that it is a borrow from local variable
(x, xref)
}
fn main() {
{
// this is OK
let x = Box::new(X { value: 10 });
let xref = f(&x);
println!("{}", xref.x.value);
}
{
// how should I do this?
let (x, xref) = g();
println!("{}", xref.x.value);
}
}
Errors:
Compiling playground v0.0.1 (/playground)
warning: unused variable: `x`
--> src/main.rs:36:14
|
36 | let (x, xref) = g();
| ^ help: consider prefixing with an underscore: `_x`
|
= note: `#[warn(unused_variables)]` on by default
error[E0515]: cannot return value referencing local variable `x`
--> src/main.rs:24:5
|
18 | let xref = XRef { x: &x };
| -- `x` is borrowed here
...
24 | (x, xref)
| ^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `x` because it is borrowed
--> src/main.rs:24:6
|
16 | fn g<'a>() -> (Box<X>, XRef<'a>) {
| -- lifetime `'a` defined here
17 | let x = Box::new(X { value: 10 });
18 | let xref = XRef { x: &x };
| -- borrow of `x` occurs here
...
24 | (x, xref)
| -^-------
| ||
| |move out of `x` occurs here
| returning this value requires that `x` is borrowed for `'a`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0505, E0515.
For more information about an error, try `rustc --explain E0505`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.