@@ -164,6 +164,16 @@ impl<T> OnceCell<T> {
164
164
}
165
165
}
166
166
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
+
167
177
/// Gets the contents of the cell, initializing it with `f` if
168
178
/// the cell was empty. If the cell was empty and `f` failed, an
169
179
/// error is returned.
@@ -200,16 +210,29 @@ impl<T> OnceCell<T> {
200
210
if let Some ( val) = self . get ( ) {
201
211
return Ok ( val) ;
202
212
}
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) ;
211
223
}
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 ( ) ?;
213
236
// Note that *some* forms of reentrant initialization might lead to
214
237
// UB (see `reentrant_init` test). I believe that just removing this
215
238
// `panic`, while keeping `try_insert` would be sound, but it seems
0 commit comments