I don't understand why the borrow must last for 'a. Are there any ways around this without using unsafe, Rc/Weak, or external crates? In my real use case, self_ref is a BTreeSet and data is an array, so using indices as opposed to references doesn't really work, and storing keys is just annoying.
fn main() {
let mut foo = Foo::default();
// If Foo::bar takes &'a mut self, this mutable borrow
// lasts as long as long as the lifetime of foo...
foo.bar();
// ... making this borrow (mutable or not), impossible.
foo.baz();
// Meanwhile, if Foo::bar takes &mut self, the borrow
// is shorter lived.
}
#[derive(Debug, Default)]
struct Foo<'a> {
self_ref: Vec<&'a i32>,
data: i32,
}
impl<'a> Foo<'a> {
fn bar(&mut self) {
let data = &self.data;
// This borrow to self.self_ref requires that the
// borrow outlives 'a.
// Annotating the borrow as &'a mut self resolves
// the error, but disallows any further borrows
// after this one.
self.self_ref.push(data);
}
fn baz(&self) {
println!("{}", self.self_ref.len());
}
}
The first thing to try is separating self_ref and data so they are not in the same struct. For example, it might work to pass them as separate parameters. I realize this is probably inconvenient, but it is worth examining.
There's no sound ways around the "borrow forever" lifetime using references, because if Foo<'a> does not remain borrowed, you could obtain an exclusive and shared reference to data at the same time, which is UB. In non-reduced use cases, it usually also means you can throw out the referenced data, opening the door to dangling references, UAFs, and the like.
For example I think you meant self_ref is an array and data is the BTreeSet (as otherwise storing indices would work fine); if you can get a &mut Foo<'_> you can clear the BTreeSet.
You could set things up so that you still have a &Foo after becoming self-referencial to make the reduced example work,[1] but it's still more restrictive than just using two different structs,[2] so not worth it IMO even if it happens to work.
TL;DR: References (&, &mut) are the wrong tool for the job.