0

I am using the vulkano library that has the two types:

PhysicalDevice takes an &Arc<Instance>. I am writing a function that returns a struct containing an Arc to instances to these classes, but, due to the fact that PhysicalDevice::enumerate requires an &Arc<Instance>, the borrow checker is not compiling the code, even if the instances live beyond the function.

I've created a smaller reproduction of the problem where Pet takes a &Arc<Person>.

In the function test, I create both objects and try to return them in a struct:

use std::sync::Arc;

struct Person {
    name: String,
}

struct Pet<'t> {
    name: String,
    owner: &'t Arc<Person>,
}

struct PersonPetPair<'a> {
    person: Arc<Person>,
    pet: Arc<Pet<'a>>,
}

fn test<'a>() -> PersonPetPair<'a> {
    let person = Person {
        name: String::from("ash"),
    };
    let person_arc = Arc::new(person);

    let pet = Pet {
        name: String::from("pikachu"),
        owner: &person_arc,
    };
    let pet_arc = Arc::new(pet);

    PersonPetPair {
        person: person_arc,
        pet: pet_arc,
    }
    // person_arc ends here, so the reference is invalid anymore
    // Still, the objects are still alive since they are created with
    // Arc<>
}

fn main() {
    let t = test();
    println!("{} owns {}", t.person.name, t.pet.name);
}

The compiler tells me there is a problem:

error[E0597]: `person_arc` does not live long enough
  --> src/main.rs:25:17
   |
25 |         owner: &person_arc,
   |                 ^^^^^^^^^^ borrowed value does not live long enough
...
36 | }
   | - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 17:9...
  --> src/main.rs:17:9
   |
17 | fn test<'a>() -> PersonPetPair<'a> {
   |         ^^

Indeed, the local variable person_arc is being dropped when the function ends. There should be a way to avoid this problem since both instances outlive the function thanks to the use of Arc.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Clynamen
  • 509
  • 1
  • 6
  • 16
  • The entire reason to use an `Arc` is so that you can have multiple owners. [Don't save a reference to the `Arc`, just clone it](https://play.rust-lang.org/?gist=b57d16849bb603324f337727793020ff&version=stable&mode=debug&edition=2015). When you call `PhysicalDevice::new`, take the reference there. – Shepmaster Sep 23 '18 at 14:21
  • @Shepmaster the method enumerate(), which I use, is indeed taking a reference https://docs.rs/vulkano/0.5/vulkano/instance/struct.PhysicalDevice.html#method.enumerate isn't this the problem? – Clynamen Sep 23 '18 at 14:30
  • I don't follow your question. You cannot store a value and a reference to that value in the same struct, as described in the duplicate. Thus you cannot store an `Arc` and a `PhysicalDevice` that references it in the same struct. In the code you have provided here, you can change it to keep whole `Arc`s, not references; perhaps you can change the library. The type `&Arc` is suspicious on the surface, honestly. Otherwise, there's really no reason to keep the `PhysicalDevice` struct around; it's super lightweight to create. – Shepmaster Sep 23 '18 at 14:54
  • Note that the code I provided is used for reproducing the problem of the library, which of course I cannot change. The question is: Due to the fact that I cannot change the library, and creating a struct in the way I tried does not work, what is the proper way to include both Instance and PhysicalDevice in a unique object? What I want to achieve is to have a class that 'hides' the vulkan stuff, so I want to put the Vulkan variables in there. Or I am supposed to carry around multiple objects through my program? – Clynamen Sep 23 '18 at 16:45
  • Thanks for the linked question, it is really useful for understanding the problem. – Clynamen Sep 23 '18 at 16:46
  • 1
    *of course I cannot change* — I don't see why not, it's an open-source project that presumably accepts pull requests. However, we cannot answer hypothetical questions about code that isn't provided. *what is the proper way to include both `Instance` and `PhysicalDevice` in a unique object* — that's what the section labeled **How do I fix it?** in the linked question is all about. I also suggested: *there's really no reason to keep the `PhysicalDevice` struct around; it's super lightweight to create*. – Shepmaster Sep 23 '18 at 16:48
  • I am checking this https://github.com/vulkano-rs/vulkano/issues/930 – Clynamen Sep 23 '18 at 17:53

0 Answers0