How do I borrow a reference to what is inside an Option<T>?
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:
- Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?
First of all, you don't need &mut self
.
When matching, you should match e
as a reference. You are trying to return a reference of e
, but the lifetime of it is only for that match statement.
enum BarErr {
Nope
}
struct Foo;
struct Bar {
data: Option<Box<Foo>>
}
impl Bar {
fn borrow(&self) -> Result<&Foo, BarErr> {
match self.data {
Some(ref x) => Ok(x),
None => Err(BarErr::Nope)
}
}
}