Skip to content

Commit b8955c5

Browse files
lolbinarycatkennytm
andcommitted
core: add Option::get_or_try_insert_with
Co-authored-by: kennytm <[email protected]>
1 parent 213d946 commit b8955c5

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
@@ -578,7 +578,7 @@
578578

579579
use crate::iter::{self, FusedIterator, TrustedLen};
580580
use crate::marker::Destruct;
581-
use crate::ops::{self, ControlFlow, Deref, DerefMut};
581+
use crate::ops::{self, ControlFlow, Deref, DerefMut, Residual, Try};
582582
use crate::panicking::{panic, panic_display};
583583
use crate::pin::Pin;
584584
use crate::{cmp, convert, hint, mem, slice};
@@ -1807,6 +1807,49 @@ impl<T> Option<T> {
18071807
unsafe { self.as_mut().unwrap_unchecked() }
18081808
}
18091809

1810+
/// If the option is `None`, calls the closure and inserts its output if successful.
1811+
///
1812+
/// If the closure returns a residual value such as `Err` or `None`,
1813+
/// that residual value is returned and nothing is inserted.
1814+
///
1815+
/// If the option is `Some`, nothing is inserted.
1816+
///
1817+
/// Unless a residual is returned, a mutable reference to the value
1818+
/// of the option will be output.
1819+
///
1820+
/// # Examples
1821+
///
1822+
/// ```
1823+
/// #![feature(option_get_or_try_insert_with)]
1824+
/// let mut o1: Option<u32> = None;
1825+
/// let mut o2: Option<u8> = None;
1826+
///
1827+
/// let number = "12345";
1828+
///
1829+
/// assert_eq!(o1.get_or_try_insert_with(|| number.parse()).copied(), Ok(12345));
1830+
/// assert!(o2.get_or_try_insert_with(|| number.parse()).is_err());
1831+
/// assert_eq!(o1, Some(12345));
1832+
/// assert_eq!(o2, None);
1833+
/// ```
1834+
#[inline]
1835+
#[unstable(feature = "option_get_or_try_insert_with", issue = "143648")]
1836+
pub fn get_or_try_insert_with<'a, R, F>(
1837+
&'a mut self,
1838+
f: F,
1839+
) -> <R::Residual as Residual<&'a mut T>>::TryType
1840+
where
1841+
F: FnOnce() -> R,
1842+
R: Try<Output = T, Residual: Residual<&'a mut T>>,
1843+
{
1844+
if let None = self {
1845+
*self = Some(f()?);
1846+
}
1847+
// SAFETY: a `None` variant for `self` would have been replaced by a `Some`
1848+
// variant in the code above.
1849+
1850+
Try::from_output(unsafe { self.as_mut().unwrap_unchecked() })
1851+
}
1852+
18101853
/////////////////////////////////////////////////////////////////////////
18111854
// Misc
18121855
/////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)