@@ -2,6 +2,7 @@ use crate::cell::UnsafeCell;
22use crate :: fmt;
33use crate :: marker:: PhantomData ;
44use crate :: mem:: MaybeUninit ;
5+ use crate :: ops:: { ControlFlow , FromResidual , Residual , Try } ;
56use crate :: panic:: { RefUnwindSafe , UnwindSafe } ;
67use crate :: sync:: Once ;
78
@@ -375,24 +376,23 @@ impl<T> OnceLock<T> {
375376 /// ```
376377 #[ inline]
377378 #[ 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
379380 where
380- F : FnOnce ( ) -> Result < T , E > ,
381+ F : FnOnce ( ) -> R ,
382+ R : Try < Output = T , Residual : Residual < & ' a T > > ,
381383 {
382384 // Fast path check
383385 // NOTE: We need to perform an acquire on the state in this method
384386 // 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+ }
389392 }
390- self . initialize ( f) ?;
391-
392- debug_assert ! ( self . is_initialized( ) ) ;
393393
394394 // SAFETY: The inner value has been initialized
395- Ok ( unsafe { self . get_unchecked ( ) } )
395+ try { unsafe { self . get_unchecked ( ) } }
396396 }
397397
398398 /// Gets the mutable reference of the contents of the cell, initializing
@@ -426,16 +426,22 @@ impl<T> OnceLock<T> {
426426 /// ```
427427 #[ inline]
428428 #[ 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
430433 where
431- F : FnOnce ( ) -> Result < T , E > ,
434+ F : FnOnce ( ) -> R ,
435+ R : Try < Output = T , Residual : Residual < & ' a mut T > > ,
432436 {
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+ }
435441 }
436- debug_assert ! ( self . is_initialized ( ) ) ;
442+
437443 // SAFETY: The inner value has been initialized
438- Ok ( unsafe { self . get_unchecked_mut ( ) } )
444+ try { unsafe { self . get_unchecked_mut ( ) } }
439445 }
440446
441447 /// Consumes the `OnceLock`, returning the wrapped value. Returns
@@ -499,22 +505,22 @@ impl<T> OnceLock<T> {
499505
500506 #[ cold]
501507 #[ optimize( size) ]
502- fn initialize < F , E > ( & self , f : F ) -> Result < ( ) , E >
508+ fn initialize < F , R > ( & self , f : F ) -> ControlFlow < R :: Residual , ( ) >
503509 where
504- F : FnOnce ( ) -> Result < T , E > ,
510+ F : FnOnce ( ) -> R ,
511+ R : Try < Output = T > ,
505512 {
506- let mut res: Result < ( ) , E > = Ok ( ( ) ) ;
507- let slot = & self . value ;
513+ let mut res = ControlFlow :: Continue ( ( ) ) ;
508514
509515 // Ignore poisoning from other threads
510516 // If another thread panics, then we'll be able to run our closure
511517 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) } ;
515521 }
516- Err ( e ) => {
517- res = Err ( e ) ;
522+ ControlFlow :: Break ( residual ) => {
523+ res = ControlFlow :: Break ( residual ) ;
518524
519525 // Treat the underlying `Once` as poisoned since we
520526 // failed to initialize our value.
0 commit comments