Skip to content

Commit 9e8f17f

Browse files
lolbinarycatkennytm
andcommitted
core: add Option::get_or_try_insert_with
Co-authored-by: kennytm <[email protected]>
1 parent 3014e79 commit 9e8f17f

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
@@ -577,7 +577,7 @@
577577
#![stable(feature = "rust1", since = "1.0.0")]
578578

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

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

0 commit comments

Comments
 (0)