Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b0d20c7

Browse files
committedFeb 14, 2024
impl get_mut_or_init and get_mut_or_try_init for OnceCell
See also rust-lang#74465 (comment) Signed-off-by: tison <wander4096@gmail.com>
1 parent bb89df6 commit b0d20c7

File tree

1 file changed

+32
-9
lines changed

1 file changed

+32
-9
lines changed
 

‎library/core/src/cell/once.rs

+32-9
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)