How to return a reference to a `Vec`

I'm trying to get the following to compile:

pub struct Foo {
    bars: Option<Vec<String>>,
}

impl Foo {
    // Get the bars, memoizing the result.
    async fn bars(&mut self) -> &[String] {
        if let Some(bars) = &self.bars {
            return Ok(bars);
        }

        self.bars = Some(get_bars().await);
        self.bars.as_ref().unwrap()
    }
}

// Expensive.
async fn get_bars() -> Vec<String> {
    todo!()
}

I have 2 problems:

  • the lifetime of the if let Some(bars) = &self.bars borrow is not the same as the &mut self in the function signature,

  • I cannot borrow self as mutable in self.bars = Some(get_bars()) because self is still borrowed as immutable 4 lines above.

How can I return the bars early in the Some case and continue the function in the None one?

fn bars(&mut self) -> &[String] {
    self.bars.get_or_insert_with(get_bars)
}
1 Like

You can't do it directly, this is a famous limitation of the current borrow checker. This should be possible to do if Polonius ever lands.

In the meantime you would have to use one of the proposed workarounds, rework your API or use unsafe.

1 Like

I should have probably mentioned that actual bars function was async and I need to .await get_bars(). I've updated my post now.