0

Given the following example:

struct A;

struct B<'a> {
    ptr: &'a A
}

struct C<'a> {
    ptr: &'a A
}

struct Context<'a> {
    a: A,
    b: B<'a>,
    c: C<'a>
}

fn setup<'a>() -> Context<'a> {
    let a = A;
    let b = B {ptr: &a};
    let c = C {ptr: &a};
    Context {a: a, b: b, c: c}
}

#[test]
fn it_works() {
    let context = setup();
}

the compiler basically complains about references to an object that is later moved:

error: `a` does not live long enough
    let b = B {ptr: &a};
                     ^
note: reference must be valid for the lifetime 'a as defined on the block at 18:30...
fn setup<'a>() -> Context<'a> {
                              ^
note: ...but borrowed value is only valid for the block suffix following statement 0 at 19:14
    let a = A;
              ^

I understand that moving out of a value is impossible as long as it's borrowed (and that is basically what happens). However, there should be a way around this as the data itself indeed lives long enough: Context has the same lifetime as B and C, so both .ptrs are valid at any time.

Does anyone know a solution for this? Background for this architecture: In a larger program I want to have a single context object that can be borrowed or moved around as needed. In order to keep dependencies at a minimum and make tests as painless as possible, submodules have their own context objects (the A and Bs in the example) whenever possible. Immutably shared data should be stored as a reference as shown in the example.

The only thing I've come up with so far is explicitly calling each submodule's function with the reference (&a) as argument which is kind of verbose.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Marc
  • 183
  • 7
  • Your code is incorrect. `a` is constructed on the stack, then moved into the `C` value, then further moved (as part of the `C`) to the caller's stack. The references become dangling very quickly. –  Jul 07 '16 at 18:36
  • Totally missed that. I somehow thought the address to A stays the same, but of course, when the function returns the Stack context changes. So, when putting `a` onto the heap, it's address should stay the same. I will play with that scenario – Marc Jul 07 '16 at 18:51
  • Fair warning: Rust will not let you do that either, because it can't in general check that the heap allocation isn't dropped while the reference is used. –  Jul 07 '16 at 19:11
  • If you think that the linked duplicate is inappropriate, [edit] your question to explain why and ping me. – Shepmaster Jul 07 '16 at 20:16
  • Shepmaster, thanks for linking your comprehensive q/a pair. Haven't found it with google or SO search before. Maybe this new link helps other people find it more easily. I will take a look at `owning_ref` but think that restructure my architecture is the better approach. – Marc Jul 08 '16 at 07:10

0 Answers0