Skip to content

Commit 17d056e

Browse files
committed
feat[core]: use Try trait to make OnceCell::get_or_try_init generic over result type
1 parent d5d0343 commit 17d056e

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

library/core/src/cell/once.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::cell::UnsafeCell;
22
use crate::fmt;
33
use crate::mem;
4+
use crate::ops::Residual;
5+
use crate::ops::Try;
46

57
/// A cell which can be written to only once.
68
///
@@ -136,8 +138,12 @@ impl<T> OnceCell<T> {
136138
}
137139

138140
/// Gets the contents of the cell, initializing it with `f` if
139-
/// the cell was empty. If the cell was empty and `f` failed, an
140-
/// error is returned.
141+
/// the cell was empty. If the cell was empty and `f` short-circuits,
142+
/// the residual is returned.
143+
///
144+
/// The return type of this method depends on the return type of the
145+
/// closure. If it returns `Result<T, E>`, the output is `Result<&T, E>`.
146+
/// If it returns `Option<T>`, the output is `Option<&T>`.
141147
///
142148
/// # Panics
143149
///
@@ -156,6 +162,7 @@ impl<T> OnceCell<T> {
156162
///
157163
/// let cell = OnceCell::new();
158164
/// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
165+
/// assert_eq!(cell.get_or_try_init(|| None), None);
159166
/// assert!(cell.get().is_none());
160167
/// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
161168
/// Ok(92)
@@ -164,19 +171,21 @@ impl<T> OnceCell<T> {
164171
/// assert_eq!(cell.get(), Some(&92))
165172
/// ```
166173
#[unstable(feature = "once_cell_try", issue = "109737")]
167-
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
174+
pub fn get_or_try_init<'a, F, R>(&'a self, f: F) -> <R::Residual as Residual<&T>>::TryType
168175
where
169-
F: FnOnce() -> Result<T, E>,
176+
F: FnOnce() -> R,
177+
R: Try<Output = T>,
178+
R::Residual: Residual<&'a T>,
170179
{
171180
if let Some(val) = self.get() {
172-
return Ok(val);
181+
return Try::from_output(val);
173182
}
174183
/// Avoid inlining the initialization closure into the common path that fetches
175184
/// the already initialized value
176185
#[cold]
177-
fn outlined_call<F, T, E>(f: F) -> Result<T, E>
186+
fn outlined_call<F, R>(f: F) -> R
178187
where
179-
F: FnOnce() -> Result<T, E>,
188+
F: FnOnce() -> R,
180189
{
181190
f()
182191
}
@@ -186,7 +195,7 @@ impl<T> OnceCell<T> {
186195
// `assert`, while keeping `set/get` would be sound, but it seems
187196
// better to panic, rather than to silently use an old value.
188197
assert!(self.set(val).is_ok(), "reentrant init");
189-
Ok(self.get().unwrap())
198+
Try::from_output(self.get().unwrap())
190199
}
191200

192201
/// Consumes the cell, returning the wrapped value.

0 commit comments

Comments
 (0)