How do I borrow a reference to what is inside an Option?

As of Rust 1.26, match ergonomics allows you to write:

impl Bar {
    fn borrow(&mut self) -> Result<&Box<Foo>, BarErr> {
        match &self.data {
            Some(e) => Ok(e),
            None => Err(BarErr::Nope),
        }
    }
}

Prior to that, you can use Option::as_ref, you just need to use it earlier:

impl Bar {
    fn borrow(&self) -> Result<&Box<Foo>, BarErr> {
        self.data.as_ref().ok_or(BarErr::Nope)
    }
}

There’s a companion method for mutable references: Option::as_mut:

impl Bar {
    fn borrow_mut(&mut self) -> Result<&mut Box<Foo>, BarErr> {
        self.data.as_mut().ok_or(BarErr::Nope)
    }
}

I’d encourage removing the Box wrapper though.

Since Rust 1.40, you can use Option::as_deref / Option::as_deref_mut:

impl Bar {
    fn borrow(&self) -> Result<&Foo, BarErr> {
        self.data.as_deref().ok_or(BarErr::Nope)
    }

    fn borrow_mut(&mut self) -> Result<&mut Foo, BarErr> {
        self.data.as_deref_mut().ok_or(BarErr::Nope)
    }
}

Before then, I’d probably use a map

impl Bar {
    fn borrow(&self) -> Result<&Foo, BarErr> {
        self.data.as_ref().map(|x| &**x).ok_or(BarErr::Nope)
    }

    fn borrow_mut(&mut self) -> Result<&mut Foo, BarErr> {
        self.data.as_mut().map(|x| &mut **x).ok_or(BarErr::Nope)
    }
}

With the match ergonomics version, you can do the mapping inline:

impl Bar {
    fn borrow(&mut self) -> Result<&Foo, BarErr> {
        match &self.data {
            Some(e) => Ok(&**e),
            None => Err(BarErr::Nope),
        }
    }

    fn borrow_mut(&mut self) -> Result<&mut Foo, BarErr> {
        match &mut self.data {
            Some(e) => Ok(&mut **e),
            None => Err(BarErr::Nope),
        }
    }
}

See also:

Leave a Comment