Skip to content

Commit d09af04

Browse files
lolbinarycatkennytm
andcommitted
core: add Option::get_or_try_insert_with
Co-authored-by: kennytm <kennytm@gmail.com>
1 parent f838cbc commit d09af04

File tree

1 file changed

+44
-1
lines changed

1 file changed

+44
-1
lines changed

library/core/src/option.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@
576576
#![stable(feature = "rust1", since = "1.0.0")]
577577

578578
use crate::iter::{self, FusedIterator, TrustedLen};
579-
use crate::ops::{self, ControlFlow, Deref, DerefMut};
579+
use crate::ops::{self, ControlFlow, Deref, DerefMut, Residual, Try};
580580
use crate::panicking::{panic, panic_display};
581581
use crate::pin::Pin;
582582
use crate::{cmp, convert, hint, mem, slice};
@@ -1758,6 +1758,49 @@ impl<T> Option<T> {
17581758
unsafe { self.as_mut().unwrap_unchecked() }
17591759
}
17601760

1761+
/// If the option is `None`, calls the closure and inserts its output if successful.
1762+
///
1763+
/// If the closure returns a residual value such as `Err` or `None`,
1764+
/// that residual value is returned and nothing is inserted.
1765+
///
1766+
/// If the option is `Some`, nothing is inserted.
1767+
///
1768+
/// Unless a residual is returned, a mutable reference to the value
1769+
/// of the option will be output.
1770+
///
1771+
/// # Examples
1772+
///
1773+
/// ```
1774+
/// #![feature(option_get_or_try_insert_with)]
1775+
/// let mut o1: Option<u32> = None;
1776+
/// let mut o2: Option<u8> = None;
1777+
///
1778+
/// let number = "12345";
1779+
///
1780+
/// assert_eq!(o1.get_or_try_insert_with(|| number.parse()).copied(), Ok(12345));
1781+
/// assert!(o2.get_or_try_insert_with(|| number.parse()).is_err());
1782+
/// assert_eq!(o1, Some(12345));
1783+
/// assert_eq!(o2, None);
1784+
/// ```
1785+
#[inline]
1786+
#[unstable(feature = "option_get_or_try_insert_with", issue = "143648")]
1787+
pub fn get_or_try_insert_with<'a, R, F>(
1788+
&'a mut self,
1789+
f: F,
1790+
) -> <R::Residual as Residual<&'a mut T>>::TryType
1791+
where
1792+
F: FnOnce() -> R,
1793+
R: Try<Output = T, Residual: Residual<&'a mut T>>,
1794+
{
1795+
if let None = self {
1796+
*self = Some(f()?);
1797+
}
1798+
// SAFETY: a `None` variant for `self` would have been replaced by a `Some`
1799+
// variant in the code above.
1800+
1801+
Try::from_output(unsafe { self.as_mut().unwrap_unchecked() })
1802+
}
1803+
17611804
/////////////////////////////////////////////////////////////////////////
17621805
// Misc
17631806
/////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)