@@ -135,6 +135,16 @@ impl<T> OnceCell<T> {
135
135
}
136
136
}
137
137
138
+ #[ inline]
139
+ pub fn get_mut_or_init < F > ( & mut self , f : F ) -> & mut T
140
+ where
141
+ F : FnOnce ( ) -> T ,
142
+ {
143
+ match self . get_mut_or_try_init ( || Ok :: < T , !> ( f ( ) ) ) {
144
+ Ok ( val) => val,
145
+ }
146
+ }
147
+
138
148
/// Gets the contents of the cell, initializing it with `f` if
139
149
/// the cell was empty. If the cell was empty and `f` failed, an
140
150
/// error is returned.
@@ -171,22 +181,35 @@ impl<T> OnceCell<T> {
171
181
if let Some ( val) = self . get ( ) {
172
182
return Ok ( val) ;
173
183
}
174
- /// Avoid inlining the initialization closure into the common path that fetches
175
- /// the already initialized value
176
- #[ cold]
177
- fn outlined_call < F , T , E > ( f : F ) -> Result < T , E >
178
- where
179
- F : FnOnce ( ) -> Result < T , E > ,
180
- {
181
- f ( )
184
+ self . try_init ( f) ?;
185
+ Ok ( self . get ( ) . unwrap ( ) )
186
+ }
187
+
188
+ pub fn get_mut_or_try_init < F , E > ( & mut self , f : F ) -> Result < & mut T , E >
189
+ where
190
+ F : FnOnce ( ) -> Result < T , E > ,
191
+ {
192
+ if let Some ( val) = self . get ( ) {
193
+ return Ok ( val) ;
182
194
}
183
- let val = outlined_call ( f) ?;
195
+ self . try_init ( f) ?;
196
+ Ok ( self . get_mut ( ) . unwrap ( ) )
197
+ }
198
+
199
+ // Avoid inlining the initialization closure into the common path that fetches
200
+ // the already initialized value
201
+ #[ cold]
202
+ fn try_init < F , E > ( & self , f : F ) -> Result < ( ) , E >
203
+ where
204
+ F : FnOnce ( ) -> Result < T , E > ,
205
+ {
206
+ let val = f ( ) ?;
184
207
// Note that *some* forms of reentrant initialization might lead to
185
208
// UB (see `reentrant_init` test). I believe that just removing this
186
209
// `assert`, while keeping `set/get` would be sound, but it seems
187
210
// better to panic, rather than to silently use an old value.
188
211
assert ! ( self . set( val) . is_ok( ) , "reentrant init" ) ;
189
- Ok ( self . get ( ) . unwrap ( ) )
212
+ Ok ( ( ) )
190
213
}
191
214
192
215
/// Consumes the cell, returning the wrapped value.
0 commit comments