@@ -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
@@ -375,24 +376,23 @@ impl<T> OnceLock<T> {
375
376
/// ```
376
377
#[ inline]
377
378
#[ unstable( feature = "once_cell_try" , issue = "109737" ) ]
378
- pub fn get_or_try_init < F , E > ( & self , f : F ) -> Result < & T , E >
379
+ pub fn get_or_try_init < ' a , F , R > ( & ' a self , f : F ) -> < R :: Residual as Residual < & ' a T > > :: TryType
379
380
where
380
- F : FnOnce ( ) -> Result < T , E > ,
381
+ F : FnOnce ( ) -> R ,
382
+ R : Try < Output = T , Residual : Residual < & ' a T > > ,
381
383
{
382
384
// Fast path check
383
385
// NOTE: We need to perform an acquire on the state in this method
384
386
// in order to correctly synchronize `LazyLock::force`. This is
385
- // currently done by calling `self.get()`, which in turn calls
386
- // `self.is_initialized()`, which in turn performs the acquire.
387
- if let Some ( value) = self . get ( ) {
388
- return Ok ( value) ;
387
+ // currently done by calling `self.is_initialized()`.
388
+ if !self . is_initialized ( ) {
389
+ if let ControlFlow :: Break ( residual) = self . initialize ( f) {
390
+ return FromResidual :: from_residual ( residual) ;
391
+ }
389
392
}
390
- self . initialize ( f) ?;
391
-
392
- debug_assert ! ( self . is_initialized( ) ) ;
393
393
394
394
// SAFETY: The inner value has been initialized
395
- Ok ( unsafe { self . get_unchecked ( ) } )
395
+ try { unsafe { self . get_unchecked ( ) } }
396
396
}
397
397
398
398
/// Gets the mutable reference of the contents of the cell, initializing
@@ -426,16 +426,22 @@ impl<T> OnceLock<T> {
426
426
/// ```
427
427
#[ inline]
428
428
#[ unstable( feature = "once_cell_get_mut" , issue = "121641" ) ]
429
- pub fn get_mut_or_try_init < F , E > ( & mut self , f : F ) -> Result < & mut T , E >
429
+ pub fn get_mut_or_try_init < ' a , F , R > (
430
+ & ' a mut self ,
431
+ f : F ,
432
+ ) -> <R :: Residual as Residual < & ' a mut T > >:: TryType
430
433
where
431
- F : FnOnce ( ) -> Result < T , E > ,
434
+ F : FnOnce ( ) -> R ,
435
+ R : Try < Output = T , Residual : Residual < & ' a mut T > > ,
432
436
{
433
- if self . get ( ) . is_none ( ) {
434
- self . initialize ( f) ?;
437
+ if !self . is_initialized ( ) {
438
+ if let ControlFlow :: Break ( residual) = self . initialize ( f) {
439
+ return FromResidual :: from_residual ( residual) ;
440
+ }
435
441
}
436
- debug_assert ! ( self . is_initialized ( ) ) ;
442
+
437
443
// SAFETY: The inner value has been initialized
438
- Ok ( unsafe { self . get_unchecked_mut ( ) } )
444
+ try { unsafe { self . get_unchecked_mut ( ) } }
439
445
}
440
446
441
447
/// Consumes the `OnceLock`, returning the wrapped value. Returns
@@ -499,22 +505,22 @@ impl<T> OnceLock<T> {
499
505
500
506
#[ cold]
501
507
#[ optimize( size) ]
502
- fn initialize < F , E > ( & self , f : F ) -> Result < ( ) , E >
508
+ fn initialize < F , R > ( & self , f : F ) -> ControlFlow < R :: Residual , ( ) >
503
509
where
504
- F : FnOnce ( ) -> Result < T , E > ,
510
+ F : FnOnce ( ) -> R ,
511
+ R : Try < Output = T > ,
505
512
{
506
- let mut res: Result < ( ) , E > = Ok ( ( ) ) ;
507
- let slot = & self . value ;
513
+ let mut res = ControlFlow :: Continue ( ( ) ) ;
508
514
509
515
// Ignore poisoning from other threads
510
516
// If another thread panics, then we'll be able to run our closure
511
517
self . once . call_once_force ( |p| {
512
- match f ( ) {
513
- Ok ( value) => {
514
- unsafe { ( & mut * slot . get ( ) ) . write ( value) } ;
518
+ match f ( ) . branch ( ) {
519
+ ControlFlow :: Continue ( value) => {
520
+ unsafe { ( & mut * self . value . get ( ) ) . write ( value) } ;
515
521
}
516
- Err ( e ) => {
517
- res = Err ( e ) ;
522
+ ControlFlow :: Break ( residual ) => {
523
+ res = ControlFlow :: Break ( residual ) ;
518
524
519
525
// Treat the underlying `Once` as poisoned since we
520
526
// failed to initialize our value.
0 commit comments