Move value and borrowed value into struct

Hi,

i'm trying to use a library, which has a function like do_something:

struct A;

impl A {
    fn do_something<'a, 'b:'a>(&'b self) -> &'a i32{
        &1
    }
}

struct B<'a> {
    a: A,
    i: &'a i32,
}

impl B<'_> {
    fn new<'a>() -> B<'a> {
        let a = A;
        let i = a.do_something();
        B {a, i}
    }
}

fn main() {
    let b = B::new();
    println!("{:?}", b.i);
}

As you can see I want to store A and the return value of do_something in a struct (B here).
However this does not seem possible:

error[E0515]: cannot return value referencing local variable `a`
  --> src/main.rs:18:9
   |
17 |         let i = a.do_something();
   |                 ---------------- `a` is borrowed here
18 |         B {a, i}
   |         ^^^^^^^^ returns a value referencing data owned by the current function

I am quite confused by this error, as this should be possible as far as I understand. I get that, the borrow of a in line 17 needs to outlive i according to the signature of do_something. However outliving is not enforced strictly (ref), and living equally as long is valid too. And this should be the case since a and i are moved into B.

Why doesn't this work? What am I missing? Can I do something about this?

1 Like

You are not allowed to hold any references to a value when you move it. If you could, it would result in a dangling reference, which would be UB to access. Therefore, to hold both an A and its borrowed value, either have the caller store the A themself, or (less idiomatically) use a self-referencing crate such as ouroboros or self_cell.

1 Like

Thank you for your answer :slight_smile:

Your suggestions work well from a practical standpoint and will be what I will do going forward.
Additionally "self-referencing struct" was the missing google term which hindered me to research this topic further.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.