@@ -2,6 +2,7 @@ use crate::cell::UnsafeCell;
2
2
use crate :: fmt;
3
3
use crate :: marker:: PhantomData ;
4
4
use crate :: mem:: MaybeUninit ;
5
+ use crate :: ops:: { ControlFlow , FromResidual , Residual , Try } ;
5
6
use crate :: panic:: { RefUnwindSafe , UnwindSafe } ;
6
7
use crate :: sync:: Once ;
7
8
@@ -173,8 +174,12 @@ impl<T> OnceLock<T> {
173
174
}
174
175
175
176
/// Gets the contents of the cell, initializing it with `f` if
176
- /// the cell was empty. If the cell was empty and `f` failed, an
177
- /// error is returned.
177
+ /// the cell was empty. If the cell was empty and `f` short-circuits,
178
+ /// the residual value is returned.
179
+ ///
180
+ /// The return type of this method depends on the return type of the
181
+ /// closure. If it returns `Result<T, E>`, the output is `Result<&T, E>`.
182
+ /// If it returns `Option<T>`, the output is `Option<&T>`.
178
183
///
179
184
/// # Panics
180
185
///
@@ -194,6 +199,7 @@ impl<T> OnceLock<T> {
194
199
///
195
200
/// let cell = OnceLock::new();
196
201
/// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
202
+ /// assert_eq!(cell.get_or_try_init(|| None), None);
197
203
/// assert!(cell.get().is_none());
198
204
/// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
199
205
/// Ok(92)
@@ -203,24 +209,30 @@ impl<T> OnceLock<T> {
203
209
/// ```
204
210
#[ inline]
205
211
#[ unstable( feature = "once_cell_try" , issue = "109737" ) ]
206
- pub fn get_or_try_init < F , E > ( & self , f : F ) -> Result < & T , E >
212
+ pub fn get_or_try_init < ' a , F , R > ( & ' a self , f : F ) -> < R :: Residual as Residual < & ' a T > > :: TryType
207
213
where
208
- F : FnOnce ( ) -> Result < T , E > ,
214
+ F : FnOnce ( ) -> R ,
215
+ R : Try < Output = T > ,
216
+ R :: Residual : Residual < & ' a T > ,
209
217
{
210
218
// Fast path check
211
219
// NOTE: We need to perform an acquire on the state in this method
212
220
// in order to correctly synchronize `LazyLock::force`. This is
213
221
// currently done by calling `self.get()`, which in turn calls
214
222
// `self.is_initialized()`, which in turn performs the acquire.
215
223
if let Some ( value) = self . get ( ) {
216
- return Ok ( value) ;
224
+ return Try :: from_output ( value) ;
217
225
}
218
- self . initialize ( f) ?;
219
226
220
- debug_assert ! ( self . is_initialized( ) ) ;
227
+ match self . initialize ( f) {
228
+ ControlFlow :: Continue ( ( ) ) => {
229
+ debug_assert ! ( self . is_initialized( ) ) ;
221
230
222
- // SAFETY: The inner value has been initialized
223
- Ok ( unsafe { self . get_unchecked ( ) } )
231
+ // SAFETY: The inner value has been initialized
232
+ Try :: from_output ( unsafe { self . get_unchecked ( ) } )
233
+ }
234
+ ControlFlow :: Break ( residual) => FromResidual :: from_residual ( residual) ,
235
+ }
224
236
}
225
237
226
238
/// Consumes the `OnceLock`, returning the wrapped value. Returns
@@ -283,30 +295,31 @@ impl<T> OnceLock<T> {
283
295
}
284
296
285
297
#[ cold]
286
- fn initialize < F , E > ( & self , f : F ) -> Result < ( ) , E >
298
+ fn initialize < F , R > ( & self , f : F ) -> ControlFlow < R :: Residual >
287
299
where
288
- F : FnOnce ( ) -> Result < T , E > ,
300
+ F : FnOnce ( ) -> R ,
301
+ R : Try < Output = T > ,
289
302
{
290
- let mut res : Result < ( ) , E > = Ok ( ( ) ) ;
303
+ let mut result = ControlFlow :: Continue ( ( ) ) ;
291
304
let slot = & self . value ;
292
305
293
306
// Ignore poisoning from other threads
294
307
// If another thread panics, then we'll be able to run our closure
295
308
self . once . call_once_force ( |p| {
296
- match f ( ) {
297
- Ok ( value) => {
309
+ match f ( ) . branch ( ) {
310
+ ControlFlow :: Continue ( value) => {
298
311
unsafe { ( & mut * slot. get ( ) ) . write ( value) } ;
299
312
}
300
- Err ( e ) => {
301
- res = Err ( e ) ;
313
+ ControlFlow :: Break ( residual ) => {
314
+ result = ControlFlow :: Break ( residual ) ;
302
315
303
316
// Treat the underlying `Once` as poisoned since we
304
317
// failed to initialize our value. Calls
305
318
p. poison ( ) ;
306
319
}
307
320
}
308
321
} ) ;
309
- res
322
+ result
310
323
}
311
324
312
325
/// # Safety
0 commit comments