let a = A::new();
let b = B::new(&a);
let c = C::new(&a,&b)
Now as a design decision I want to have the setup of the library away from the main function, but still access the fields till the end of main function.
Two solutions I found for this:
Self-referential struct with ouroboros
Wrapping the application with the library by sending the whole "main" to the setup process.
Both of these work, and I favor the first one, but I am wondering if there is a more idiomatic/native way of solving this issue.
Generally, there are two perspectives on this problem:
It’s a limitation of Rust that self-referential structs can’t be constructed natively. (Except in the form of async {} futures, which can have references to their own contents with the help of Pin.) Perhaps someday we can come up with a way to extend the language to build such structs with less trickery than ouroboros (or yoke, self_cell, etc.) use. (Whatever this method is, it will definitely involve Pin or the successor to Pin.)
Given that the above is not available now (and may not ever be; or in some people’s opinions, should not be), the library should be considered flawed if it does not provide you an alternative to borrowing, such as using Cow<A> or Arc<A> instead of &A.
As to solutions, a third option, if your initialization is genuinely in main() and nowhere else ever, is to use Box::leak() to allocate memory for A and B and never drop them, obtaining &'static references.
Thank you for your help, the library does in fact strictly use references and no Cow/Arc, but it is not surprising since it is still in development. I will look into Box::leak().
Especially if the library is still in development, you should consider contributing a fix for the problem. One possible shape of a fix is to make it generic over a trait that is implemented for all of A, &A, Arc<A>, etc., or — if it makes sense to always require a pointer — make it generic over P: Deref<Target = A>.
Library authors often don’t realize how serious a problem this is, because it is not a problem for test cases and simple “batch processing”-shaped programs, and only shows up as an issue in more complex applications with more separation of concerns and other constraints on the control flow.