I have some structs containing some data that look like this:
struct A { // Some data}struct B<'s> { a: &'s mut A c: C<'s>}impl<'s> B<'s> { fn new(a: &'s mut A, d: &'s D) -> B<'s> { let c = C::new(d); B { a, c } } fn extract_c(self) -> C<'s> { self.c }}// A smart pointer provided by a librarystruct C<'s> { d: &'s D, // Other fields holding some data, not referencing A}struct D { // Some other data not referencing A in any way (provided by a library)}
I also have functions that that create and modify said structs like this:
fn modify(b: &mut B) { // Modifies b.a and b.c}fn construct_c<'s>(a: &'s mut A, d: &'s D) -> C<'s> { let mut b = B::new(a, d); // C is created in B::new modify(&mut b); b.extract_c()}
I want to use construct_c
somewhere else such that I can make another reference to A after obtaining the result from the call, like this:
fn main() { let mut a = A::new(); let d = D::new(); let c = construct_c(&mut a, &d); // First mutable borrow of `a` println!("{a}"); // Second borrow of `a` let result = do_sth_with_c(c); // Move of `c` do_sth_with_a(a); // Some other code...}
However, when I try to do that, the compiler says that when I call do_sth_with_c
, I am using the first mutable borrow of a
, even though c
doesn't hold the reference to a
provided to construct_c
.
When I removed println!("{a}");
and do_sth_with_a
the code compiles, but I really need to print that information and do it before calling do_sth_with_c
. Is there a way to tell the compiler that C
knows nothing about the reference to a
and that it is safe to make new references after calling construct_c
?
EDIT 1:When I substituted all the references &mut A
with Rc<RefCell<A>>
the code compiles. But is there another way without using Rc
and RefCell
?
EDIT 2:Following this answer, introducing another lifetime to B
seems to resolve the issue.
How B
changed:
struct B<'a, 's> { a: &'a mut A, c: C<'s>,}// All functions that use `B` need to be updated as well