@@ -164,6 +164,16 @@ impl<T> OnceCell<T> {
164164 }
165165 }
166166
167+ #[ inline]
168+ pub fn get_mut_or_init < F > ( & mut self , f : F ) -> & mut T
169+ where
170+ F : FnOnce ( ) -> T ,
171+ {
172+ match self . get_mut_or_try_init ( || Ok :: < T , !> ( f ( ) ) ) {
173+ Ok ( val) => val,
174+ }
175+ }
176+
167177 /// Gets the contents of the cell, initializing it with `f` if
168178 /// the cell was empty. If the cell was empty and `f` failed, an
169179 /// error is returned.
@@ -200,16 +210,29 @@ impl<T> OnceCell<T> {
200210 if let Some ( val) = self . get ( ) {
201211 return Ok ( val) ;
202212 }
203- /// Avoid inlining the initialization closure into the common path that fetches
204- /// the already initialized value
205- #[ cold]
206- fn outlined_call < F , T , E > ( f : F ) -> Result < T , E >
207- where
208- F : FnOnce ( ) -> Result < T , E > ,
209- {
210- f ( )
213+ self . try_init ( f) ?;
214+ Ok ( self . get ( ) . unwrap ( ) )
215+ }
216+
217+ pub fn get_mut_or_try_init < F , E > ( & mut self , f : F ) -> Result < & mut T , E >
218+ where
219+ F : FnOnce ( ) -> Result < T , E > ,
220+ {
221+ if let Some ( val) = self . get_mut ( ) {
222+ return Ok ( val) ;
211223 }
212- let val = outlined_call ( f) ?;
224+ self . try_init ( f) ?;
225+ Ok ( self . get_mut ( ) . unwrap ( ) )
226+ }
227+
228+ // Avoid inlining the initialization closure into the common path that fetches
229+ // the already initialized value
230+ #[ cold]
231+ fn try_init < F , E > ( & self , f : F ) -> Result < ( ) , E >
232+ where
233+ F : FnOnce ( ) -> Result < T , E > ,
234+ {
235+ let val = f ( ) ?;
213236 // Note that *some* forms of reentrant initialization might lead to
214237 // UB (see `reentrant_init` test). I believe that just removing this
215238 // `panic`, while keeping `try_insert` would be sound, but it seems
0 commit comments