Lifetime reference among struct data fields - rust

I have the following code which will throw me this error. Basically I want C to reference B which has reference to A.
How can I achieve this in Rust? Is it possible to do this with multiple life time?
Btw that I do not want to use Rc. Also I do not want C to own B.
struct A;
struct B<'a> {
a: &'a A,
}
struct C<'a> {
b: &'a B<'a>,
}
struct D<'a> {
a: &'a A,
b: B<'a>,
c: C<'a>,
}
impl<'a> D<'a> {
pub fn new(a: &'a A) -> D<'a> {
let b = B { a };
let c = C { b: &b };
D { a, b, c }
}
}
fn main() {
let a = A;
let d = D::new(&a);
}
error[E0515]: cannot return value referencing local variable `b`
--> src/main.rs:22:9
|
20 | let c = C { b: &b };
| -- `b` is borrowed here
21 |
22 | D { a, b, c }
| ^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `b` because it is borrowed
--> src/main.rs:22:16
|
17 | impl<'a> D<'a> {
| -- lifetime `'a` defined here
...
20 | let c = C { b: &b };
| -- borrow of `b` occurs here
21 |
22 | D { a, b, c }
| -------^-----
| | |
| | move out of `b` occurs here
| returning this value requires that `b` is borrowed for `'a`
Rust playground

Actually this seems to do the trick...
struct A
{
}
struct B<'a>
{
pub a : &'a A
}
struct C<'a, 'b>
{
pub b : &'b B<'a>
}
struct D<'a, 'b>
{
a : &'a A,
b : B<'a>,
c : Option<C<'a, 'b>>
}
impl<'a, 'b> D<'a, 'b>
{
pub fn new(_a:&'a A) -> D<'a, 'b>
{
let _b = B{ a : _a };
D
{
a : _a,
b : _b,
c : None,
}
}
pub fn calc(&'b mut self)
{
self.c = Some( C{ b : &self.b } );
}
}
fn test()
{
let a = A{};
let mut d = D::new(&a);
d.calc();
}

Related

how to fix 'creates a temporary which is freed while still in use'?

I'm learning Rust and trying to implement a cache-like struct to cache an object, but I'm stuck on an error.
src/main.rs
// The Result object to be cached
struct Result {
value: u32,
}
struct Cacher<'a, T>
where
T: Fn(u32) -> u32,
{
calc: T,
value: Option<&'a Result>,
}
impl<'a, T> Cacher<'a, T>
where
T: Fn(u32) -> u32,
{
fn new(calc: T) -> Cacher<'a, T> {
Cacher { calc, value: None }
}
fn get_value(&mut self, arg: u32) -> &Result {
match self.value {
Some(v) => v,
None => {
let v = (self.calc)(arg);
self.value = Some(&Result { value: v });
self.value.unwrap()
}
}
}
}
This results in the following error:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:28:40
|
15 | impl<'a, T> Cacher<'a, T>
| -- lifetime `'a` defined here
...
28 | self.value = Some(&Result { value: v });
| -------------------^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
| | |
| | creates a temporary which is freed while still in use
| assignment requires that borrow lasts for `'a`
How would one fix this?
You cannot return a reference to a value if no one owns this value.
Also when you are using your Cacher you need to ensure that reference you've got by get_value will not outlive Cacher itself.
// The Result object to be cached
struct Result {
value: u32,
}
struct Cacher<T>
where
T: Fn(u32) -> u32,
{
calc: T,
value: Option<Result>, // We need to own the Result
}
impl<T> Cacher<T>
where
T: Fn(u32) -> u32,
{
fn new(calc: T) -> Cacher<T> {
Cacher { calc, value: None }
}
fn get_value(&mut self, arg: u32) -> &Result {
match self.value {
Some(ref v) => v, // destructuring value by reference to it
None => {
let v = (self.calc)(arg);
self.value = Some(Result { value: v });
self.value.as_ref().unwrap() // unwrapping value by reference to it
}
}
}
}

How can I store a type directly in a struct when all the traits I need are implemented for references to that type?

Petgraph implements all its traits for references to it's internal graph type. How can I store and use a Graph rather than an &Graph in a struct?
This works but stores a reference to the graph:
extern crate petgraph;
use crate::petgraph::visit::*;
use petgraph::data::*;
use petgraph::*;
struct StateMachine<G>
where
G: GraphBase,
{
state_network: G,
state: <G as GraphBase>::NodeId,
}
impl<G> StateMachine<G>
where
G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase,
<G as Data>::NodeWeight: Eq + Copy,
<G as Data>::EdgeWeight: Eq + Copy,
{
pub fn next(&mut self, input: <G as Data>::EdgeWeight) -> Option<<G as Data>::NodeWeight> {
for edge in self.state_network.edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match self.state_network.node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(network: G, start: <G as Data>::NodeWeight) -> Option<StateMachine<G>> {
for nr in network.node_references() {
if *(network.node_weight(nr.id())).unwrap() == start {
return Option::Some(StateMachine {
state_network: network,
state: nr.id(),
});
}
}
return Option::None;
}
}
fn main() {
let mut sn: Graph<&str, u32, petgraph::Directed> = Graph::new();
let sn_item1 = sn.add_node("a");
let sn_item2 = sn.add_node("b");
let sn_item3 = sn.add_node("c");
let sn_item4 = sn.add_node("d");
let sn_item5 = sn.add_node("e");
sn.add_edge(sn_item1, sn_item2, 1);
sn.add_edge(sn_item1, sn_item3, 2);
sn.add_edge(sn_item2, sn_item4, 1);
sn.add_edge(sn_item2, sn_item5, 2);
sn.add_edge(sn_item5, sn_item1, 2);
sn.add_edge(sn_item5, sn_item3, 1);
let mut sm = StateMachine::new(&sn, "a").unwrap();
println!("{}", sm.next(1).unwrap());
}
Link to rust playground
But storing the Graph directly doesn't work
extern crate petgraph;
use crate::petgraph::visit::*;
use petgraph::data::*;
use petgraph::*;
struct StateMachine<'a, G>
where
&'a G: GraphBase,
{
state_network: G,
state: <&'a G as GraphBase>::NodeId,
}
impl<'a, G> StateMachine<'a, G>
where
&'a G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase,
<&'a G as Data>::NodeWeight: Eq + Copy,
<&'a G as Data>::EdgeWeight: Eq + Copy,
{
pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
for edge in (&self.state_network).edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match (&self.state_network).node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(network: G, start: <&'a G as Data>::NodeWeight) -> Option<StateMachine<'a, G>> {
for nr in network.node_references() {
if *((&network).node_weight(nr.id())).unwrap() == start {
return Option::Some(StateMachine {
state_network: network,
state: nr.id(),
});
}
}
return Option::None;
}
}
fn main() {
let mut sn: Graph<&str, u32, petgraph::Directed> = Graph::new();
let sn_item1 = sn.add_node("a");
let sn_item2 = sn.add_node("b");
let sn_item3 = sn.add_node("c");
let sn_item4 = sn.add_node("d");
let sn_item5 = sn.add_node("e");
sn.add_edge(sn_item1, sn_item2, 1);
sn.add_edge(sn_item1, sn_item3, 2);
sn.add_edge(sn_item2, sn_item4, 1);
sn.add_edge(sn_item2, sn_item5, 2);
sn.add_edge(sn_item5, sn_item1, 2);
sn.add_edge(sn_item5, sn_item3, 1);
let mut sm = StateMachine::new(sn, "a").unwrap();
println!("{}", sm.next(1).unwrap());
}
Link to rust playgound
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:29:21
|
29 | for edge in (&self.state_network).edges(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
--> src/main.rs:28:5
|
28 | / pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
29 | | for edge in (&self.state_network).edges(self.state) {
30 | | if *edge.weight() == input {
31 | | self.state = edge.target();
... |
38 | | return Option::None;
39 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:29:21
|
29 | for edge in (&self.state_network).edges(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> src/main.rs:15:6
|
15 | impl<'a, G> StateMachine<'a, G>
| ^^
= note: ...so that the expression is assignable:
expected <&G as petgraph::visit::GraphBase>::NodeId
found <&'a G as petgraph::visit::GraphBase>::NodeId
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:32:30
|
32 | return match (&self.state_network).node_weight(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
--> src/main.rs:28:5
|
28 | / pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
29 | | for edge in (&self.state_network).edges(self.state) {
30 | | if *edge.weight() == input {
31 | | self.state = edge.target();
... |
38 | | return Option::None;
39 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:32:30
|
32 | return match (&self.state_network).node_weight(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> src/main.rs:15:6
|
15 | impl<'a, G> StateMachine<'a, G>
| ^^
= note: ...so that the expression is assignable:
expected <&G as petgraph::visit::GraphBase>::NodeId
found <&'a G as petgraph::visit::GraphBase>::NodeId
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
I am not familiar with petgraph and its concepts now. From my experience storing references in structs almost always ends with complete rewrites so my approach would have been something like this:
struct StateMachine<G, E, N>
where
G: GraphBase<EdgeId = E, NodeId = N>,
E: Copy + PartialEq,
N: Copy + PartialEq,
{
state_network: G,
state: N,
}
impl<G, E, N, EW, NW> StateMachine<G, E, N>
where
G: Data<NodeWeight = NW, EdgeWeight = EW>
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase<EdgeId = E, NodeId = N>,
E: Copy + PartialEq,
N: Copy + PartialEq,
for<'a> &'a G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data<NodeWeight = NW, EdgeWeight = EW>
+ GraphBase<EdgeId = E, NodeId = N>,
EW: Eq + Copy,
NW: Eq + Copy,
{
pub fn next<'a, 'b: 'a>(&'a mut self, input: EW) -> Option<NW> {
for edge in (&self.state_network).edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match self.state_network.node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(
network: G,
start: NW,
) -> Option<StateMachine<G, <G as GraphBase>::EdgeId, <G as GraphBase>::NodeId>> {
let mut found = Option::None;
for nr in network.node_references() {
if *(network.node_weight(nr.id())).unwrap() == start {
found = Option::Some(nr.id());
}
}
found.map(|id| StateMachine {
state_network: network,
state: id,
})
}
}
EdgeId and NodeId get generic parameters (E,N)since these are reused in the implementation of StateMachine, NodeWeight and EdgeWeight also get generic (NW, EW) but only to join the associated types of &Graph and Graph.

How can I write a boxed closure which mutates a reference to a struct?

I have some code that looks like this:
type Callback<T> = Box<Fn(&T) -> ()>;
struct Foo {
name: String,
}
impl Foo {
fn name_updater(&mut self) -> Callback<String> {
Box::new(|new_name| {
self.name = *new_name;
})
}
}
This code doesn't compile because the closure requires the static lifetime. However I'm unsure if this will resolve the question and because there aren't explicit lifetimes, it's not immediately clear to me what I'd need to do to resolve that.
Here is an example of the compilation error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/lib.rs:9:9
|
9 | / Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
| |__________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
--> src/lib.rs:8:5
|
8 | / fn name_updater(&mut self) -> Callback<String> {
9 | | Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
12 | | }
| |_____^
note: ...so that the type `[closure#src/lib.rs:9:18: 11:10 self:&mut &mut Foo]` will meet its required lifetime bounds
--> src/lib.rs:9:9
|
9 | / Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
| |__________^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r std::string::String) + 'static)>
found std::boxed::Box<dyn for<'r> std::ops::Fn(&'r std::string::String)>
How can I write a closure that is capable of mutating the struct's name property?
You need to bound a lifetime to your closure because you borrow something aka &mut self:
type Callback<'a, T> = Box<dyn FnMut(&T) -> () + 'a>;
#[derive(Debug)]
struct Foo {
name: String,
}
impl Foo {
fn name_updater(&mut self) -> Callback<str> {
Box::new(move |new_name| {
self.name.replace_range(.., new_name);
})
}
}
fn main() {
let mut foo = Foo {
name: String::from("foo"),
};
foo.name_updater()("bar");
println!("{:?}", foo);
}
Also note that you don't need to use a box:
#[derive(Debug)]
struct Foo {
name: String,
}
impl Foo {
fn name_updater<'a>(&'a mut self) -> impl FnMut(&str) -> () + 'a {
move |new_name| {
self.name.replace_range(.., new_name);
}
}
}
fn main() {
let mut foo = Foo {
name: String::from("foo"),
};
foo.name_updater()("bar");
println!("{:?}", foo);
}

Is it possible to have a structure that has a reference to a sub-structure whose lifetime can be shorter?

I want to write the equivalent of this C++ in Rust:
struct Bar { int x; };
struct Foo { Bar* bar; };
void main() {
Bar bar { 42 };
Foo foo { &bar };
Bar bar2 { 50 };
foo.bar = &bar2;
printf("%d\n", foo.bar->x);
}
The C++ sets up a structure, then swaps out a Bar object with another Bar object. This is the code I've tried:
struct Bar(isize);
impl Bar {
fn new(i: isize) -> Bar { Bar(i) }
}
struct Foo<'a> {
bar: Option<&'a Bar>,
}
impl<'a> Foo<'a> {
fn new(bar: &Bar) -> Foo {
Foo { bar: Some(&bar) }
}
}
fn main() {
// Set up first state
let bar = Bar::new(42);
let mut foo = Foo::new(&bar);
// Replace bar object
let bar2 = Bar::new(50);
foo.bar = Some(&bar2);
if let Some(e) = foo.bar {
println!("{}", e.0);
}
}
This code complains:
error[E0597]: `bar2` does not live long enough
--> src/main.rs:22:21
|
22 | foo.bar = Some(&bar2);
| ^^^^ borrowed value does not live long enough
...
27 | }
| - `bar2` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
Is it possible in Rust to have a structure that has a reference to a sub-structure whose lifetime can be shorter (i.e. you can replace the sub-structure instance with another instance)?
I looked at some other answers, and tried to split up the structure:
struct Bar(isize);
impl Bar {
fn new(i: isize) -> Bar {
Bar(i)
}
}
struct FooCore {
a: isize,
}
struct Foo<'c, 'a> {
core: &'c FooCore,
bar: &'a Bar,
}
impl<'c, 'a> Foo<'c, 'a> {
fn new(core: &'c FooCore, bar: &'a Bar) -> Foo<'c, 'a> {
Foo {
core: &core,
bar: &bar,
}
}
}
fn main() {
// Set up first state
let core = FooCore { a: 10 };
let bar = Bar::new(42);
let _foo = Foo::new(&core, &bar);
// Replace bar object
let bar2 = Bar::new(50);
let foo = Foo::new(&core, &bar2);
println!("{} {}", foo.core.a, foo.bar.0);
}
This compiles and works, however, as soon as I make the core and bar fields mutable, it falls apart. Below is code that uses mut:
#![allow(unused_mut)]
struct Bar(isize);
impl Bar {
fn new(i: isize) -> Bar {
Bar(i)
}
}
struct FooCore {
a: isize,
}
struct Foo<'c, 'a> {
core: &'c mut FooCore,
bar: &'a mut Bar,
}
impl<'c, 'a> Foo<'c, 'a> {
fn new(core: &'c mut FooCore, bar: &'a mut Bar) -> Foo<'c, 'a> {
Foo {
core: &mut core,
bar: &mut bar,
}
}
}
fn main() {
// Set up first state
let mut core = FooCore { a: 10 };
let mut bar = Bar::new(42);
let mut _foo = Foo::new(&mut core, &mut bar);
// Replace bar object
let mut bar2 = Bar::new(50);
let mut foo = Foo::new(&mut core, &mut bar2);
println!("{} {}", foo.core.a, foo.bar.0);
}
This results in the errors:
error[E0597]: `core` does not live long enough
--> src/main.rs:21:24
|
21 | core: &mut core,
| ^^^^ borrowed value does not live long enough
...
24 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'c as defined on the impl at 18:1...
--> src/main.rs:18:1
|
18 | impl<'c, 'a> Foo<'c, 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0597]: `bar` does not live long enough
--> src/main.rs:22:23
|
22 | bar: &mut bar,
| ^^^ borrowed value does not live long enough
23 | }
24 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 18:1...
--> src/main.rs:18:1
|
18 | impl<'c, 'a> Foo<'c, 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0499]: cannot borrow `core` as mutable more than once at a time
--> src/main.rs:35:33
|
31 | let mut _foo = Foo::new(&mut core, &mut bar);
| ---- first mutable borrow occurs here
...
35 | let mut foo = Foo::new(&mut core, &mut bar2);
| ^^^^ second mutable borrow occurs here
...
38 | }
| - first borrow ends here
How do I structure my data to achieve what I want?
The obvious problem is that you are taking a reference to a reference unnecesarily:
In this code, core and bar are already references, so no need to get its address:
impl<'c, 'a> Foo<'c, 'a> {
fn new(core: &'c mut FooCore, bar: &'a mut Bar) -> Foo<'c, 'a> {
Foo {
core: &mut core,
bar: &mut bar,
}
}
}
Write instead:
impl<'c, 'a> Foo<'c, 'a> {
fn new(core: &'c mut FooCore, bar: &'a mut Bar) -> Foo<'c, 'a> {
Foo {
core: core,
bar: bar,
}
}
}
About the subobject living longer than the main object, the general answer is "no, you can't", because the reference could be left dangling and Rust will not allow it. There are workarounds, as the linked answer in the comments above shows.
As an extra workaround to mimic your C code, you could write:
fn main() {
// Set up first state
let mut core = FooCore { a: 10 };
let mut bar = Bar::new(42);
let mut bar2; //lifetime of bar2 is greater than foo!
let mut foo = Foo::new(&mut core, &mut bar);
bar2 = Bar::new(50); //delayed initialization
// Replace bar object
foo.bar = &mut bar2;
println!("{} {}", foo.core.a, foo.bar.0);
}

What is the correct way to use lifetimes with a struct in Rust?

I want to write this structure:
struct A {
b: B,
c: C,
}
struct B {
c: &C,
}
struct C;
The B.c should be borrowed from A.c.
A ->
b: B ->
c: &C -- borrow from --+
|
c: C <------------------+
This is what I tried:
struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: C,
}
impl<'a> A<'a> {
fn new<'b>() -> A<'b> {
let c = C;
A {
c: c,
b: B { c: &c },
}
}
}
fn main() {}
But it fails:
error[E0597]: `c` does not live long enough
--> src/main.rs:17:24
|
17 | b: B { c: &c },
| ^ borrowed value does not live long enough
18 | }
19 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'b as defined on the method body at 13:5...
--> src/main.rs:13:5
|
13 | fn new<'b>() -> A<'b> {
| ^^^^^^^^^^^^^^^^^^^^^
error[E0382]: use of moved value: `c`
--> src/main.rs:17:24
|
16 | c: c,
| - value moved here
17 | b: B { c: &c },
| ^ value used here after move
|
= note: move occurs because `c` has type `C`, which does not implement the `Copy` trait
I've read the Rust documentation on ownership, but I still don't know how to fix it.
There is actually more than one reason why the code above fails. Let's break it down a little and explore a few options on how to fix it.
First let's remove the new and try building an instance of A directly in main, so that you see that the first part of the problem has nothing to do with lifetimes:
struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: C,
}
fn main() {
// I copied your new directly here
// and renamed c1 so we know what "c"
// the errors refer to
let c1 = C;
let _ = A {
c: c1,
b: B { c: &c1 },
};
}
this fails with:
error[E0382]: use of moved value: `c1`
--> src/main.rs:20:20
|
19 | c: c1,
| -- value moved here
20 | b: B { c: &c1 },
| ^^ value used here after move
|
= note: move occurs because `c1` has type `C`, which does not implement the `Copy` trait
what it says is that if you assign c1 to c, you move its ownership to c (i.e. you can't access it any longer through c1, only through c). This means that all the references to c1 would be no longer valid. But you have a &c1 still in scope (in B), so the compiler can't let you compile this code.
The compiler hints at a possible solution in the error message when it says that type C is non-copyable. If you could make a copy of a C, your code would then be valid, because assigning c1 to c would create a new copy of the value instead of moving ownership of the original copy.
We can make C copyable by changing its definition like this:
#[derive(Copy, Clone)]
struct C;
Now the code above works. Note that what #matthieu-m comments is still true: we can't store both the reference to a value and the value itself in B (we're storing a reference to a value and a COPY of the value here). That's not just for structs, though, it's how ownership works.
Now, if you don't want to (or can't) make C copyable, you can store references in both A and B instead.
struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: &'a C, // now this is a reference too
}
fn main() {
let c1 = C;
let _ = A {
c: &c1,
b: B { c: &c1 },
};
}
All good then? Not really... we still want to move the creation of A back into a new method. And THAT's where we will run in trouble with lifetimes. Let's move the creation of A back into a method:
impl<'a> A<'a> {
fn new() -> A<'a> {
let c1 = C;
A {
c: &c1,
b: B { c: &c1 },
}
}
}
as anticipated, here's our lifetime error:
error[E0597]: `c1` does not live long enough
--> src/main.rs:17:17
|
17 | c: &c1,
| ^^ borrowed value does not live long enough
...
20 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 13:1...
--> src/main.rs:13:1
|
13 | impl<'a> A<'a> {
| ^^^^^^^^^^^^^^
error[E0597]: `c1` does not live long enough
--> src/main.rs:18:24
|
18 | b: B { c: &c1 },
| ^^ borrowed value does not live long enough
19 | }
20 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 13:1...
--> src/main.rs:13:1
|
13 | impl<'a> A<'a> {
| ^^^^^^^^^^^^^^
this is because c1 is destroyed at the end of the new method, so we can't return a reference to it.
fn new() -> A<'a> {
let c1 = C; // we create c1 here
A {
c: &c1, // ...take a reference to it
b: B { c: &c1 }, // ...and another
}
} // and destroy c1 here (so we can't return A with a reference to c1)
One possible solution is to create C outside of new and pass it in as a parameter:
struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: &'a C
}
fn main() {
let c1 = C;
let _ = A::new(&c1);
}
impl<'a> A<'a> {
fn new(c: &'a C) -> A<'a> {
A {c: c, b: B{c: c}}
}
}
playground
After checking with Manishearth and eddyb on the #rust IRC, I believe it's not possible for a struct to store a reference to itself or a portion of itself. So what you are trying to do isn't possible within Rust's type system.
Late to the party (replying from the future) and totally new to Rust, but I am getting there (sort of). Building on the answer this worked for me, at least compile wise.
impl<'a> A<'a> {
fn new() -> A<'a> {
let c1:&'a C = &C;
A {
c: c1,
b: B { c: c1 },
}
}
}

Resources