1 | use crate::cell::UnsafeCell; |
2 | use crate::{fmt, mem}; |
3 | |
4 | /// A cell which can nominally be written to only once. |
5 | /// |
6 | /// This allows obtaining a shared `&T` reference to its inner value without copying or replacing |
7 | /// it (unlike [`Cell`]), and without runtime borrow checks (unlike [`RefCell`]). However, |
8 | /// only immutable references can be obtained unless one has a mutable reference to the cell |
9 | /// itself. In the same vein, the cell can only be re-initialized with such a mutable reference. |
10 | /// |
11 | /// A `OnceCell` can be thought of as a safe abstraction over uninitialized data that becomes |
12 | /// initialized once written. |
13 | /// |
14 | /// For a thread-safe version of this struct, see [`std::sync::OnceLock`]. |
15 | /// |
16 | /// [`RefCell`]: crate::cell::RefCell |
17 | /// [`Cell`]: crate::cell::Cell |
18 | /// [`std::sync::OnceLock`]: ../../std/sync/struct.OnceLock.html |
19 | /// |
20 | /// # Examples |
21 | /// |
22 | /// ``` |
23 | /// use std::cell::OnceCell; |
24 | /// |
25 | /// let cell = OnceCell::new(); |
26 | /// assert!(cell.get().is_none()); |
27 | /// |
28 | /// let value: &String = cell.get_or_init(|| { |
29 | /// "Hello, World!" .to_string() |
30 | /// }); |
31 | /// assert_eq!(value, "Hello, World!" ); |
32 | /// assert!(cell.get().is_some()); |
33 | /// ``` |
34 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
35 | pub struct OnceCell<T> { |
36 | // Invariant: written to at most once. |
37 | inner: UnsafeCell<Option<T>>, |
38 | } |
39 | |
40 | impl<T> OnceCell<T> { |
41 | /// Creates a new uninitialized cell. |
42 | #[inline ] |
43 | #[must_use ] |
44 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
45 | #[rustc_const_stable (feature = "once_cell" , since = "1.70.0" )] |
46 | pub const fn new() -> OnceCell<T> { |
47 | OnceCell { inner: UnsafeCell::new(None) } |
48 | } |
49 | |
50 | /// Gets the reference to the underlying value. |
51 | /// |
52 | /// Returns `None` if the cell is uninitialized. |
53 | #[inline ] |
54 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
55 | pub fn get(&self) -> Option<&T> { |
56 | // SAFETY: Safe due to `inner`'s invariant |
57 | unsafe { &*self.inner.get() }.as_ref() |
58 | } |
59 | |
60 | /// Gets the mutable reference to the underlying value. |
61 | /// |
62 | /// Returns `None` if the cell is uninitialized. |
63 | #[inline ] |
64 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
65 | pub fn get_mut(&mut self) -> Option<&mut T> { |
66 | self.inner.get_mut().as_mut() |
67 | } |
68 | |
69 | /// Initializes the contents of the cell to `value`. |
70 | /// |
71 | /// # Errors |
72 | /// |
73 | /// This method returns `Ok(())` if the cell was uninitialized |
74 | /// and `Err(value)` if it was already initialized. |
75 | /// |
76 | /// # Examples |
77 | /// |
78 | /// ``` |
79 | /// use std::cell::OnceCell; |
80 | /// |
81 | /// let cell = OnceCell::new(); |
82 | /// assert!(cell.get().is_none()); |
83 | /// |
84 | /// assert_eq!(cell.set(92), Ok(())); |
85 | /// assert_eq!(cell.set(62), Err(62)); |
86 | /// |
87 | /// assert!(cell.get().is_some()); |
88 | /// ``` |
89 | #[inline ] |
90 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
91 | pub fn set(&self, value: T) -> Result<(), T> { |
92 | match self.try_insert(value) { |
93 | Ok(_) => Ok(()), |
94 | Err((_, value)) => Err(value), |
95 | } |
96 | } |
97 | |
98 | /// Initializes the contents of the cell to `value` if the cell was |
99 | /// uninitialized, then returns a reference to it. |
100 | /// |
101 | /// # Errors |
102 | /// |
103 | /// This method returns `Ok(&value)` if the cell was uninitialized |
104 | /// and `Err((¤t_value, value))` if it was already initialized. |
105 | /// |
106 | /// # Examples |
107 | /// |
108 | /// ``` |
109 | /// #![feature(once_cell_try_insert)] |
110 | /// |
111 | /// use std::cell::OnceCell; |
112 | /// |
113 | /// let cell = OnceCell::new(); |
114 | /// assert!(cell.get().is_none()); |
115 | /// |
116 | /// assert_eq!(cell.try_insert(92), Ok(&92)); |
117 | /// assert_eq!(cell.try_insert(62), Err((&92, 62))); |
118 | /// |
119 | /// assert!(cell.get().is_some()); |
120 | /// ``` |
121 | #[inline ] |
122 | #[unstable (feature = "once_cell_try_insert" , issue = "116693" )] |
123 | pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { |
124 | if let Some(old) = self.get() { |
125 | return Err((old, value)); |
126 | } |
127 | |
128 | // SAFETY: This is the only place where we set the slot, no races |
129 | // due to reentrancy/concurrency are possible, and we've |
130 | // checked that slot is currently `None`, so this write |
131 | // maintains the `inner`'s invariant. |
132 | let slot = unsafe { &mut *self.inner.get() }; |
133 | Ok(slot.insert(value)) |
134 | } |
135 | |
136 | /// Gets the contents of the cell, initializing it to `f()` |
137 | /// if the cell was uninitialized. |
138 | /// |
139 | /// # Panics |
140 | /// |
141 | /// If `f()` panics, the panic is propagated to the caller, and the cell |
142 | /// remains uninitialized. |
143 | /// |
144 | /// It is an error to reentrantly initialize the cell from `f`. Doing |
145 | /// so results in a panic. |
146 | /// |
147 | /// # Examples |
148 | /// |
149 | /// ``` |
150 | /// use std::cell::OnceCell; |
151 | /// |
152 | /// let cell = OnceCell::new(); |
153 | /// let value = cell.get_or_init(|| 92); |
154 | /// assert_eq!(value, &92); |
155 | /// let value = cell.get_or_init(|| unreachable!()); |
156 | /// assert_eq!(value, &92); |
157 | /// ``` |
158 | #[inline ] |
159 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
160 | pub fn get_or_init<F>(&self, f: F) -> &T |
161 | where |
162 | F: FnOnce() -> T, |
163 | { |
164 | match self.get_or_try_init(|| Ok::<T, !>(f())) { |
165 | Ok(val) => val, |
166 | } |
167 | } |
168 | |
169 | /// Gets the mutable reference of the contents of the cell, |
170 | /// initializing it to `f()` if the cell was uninitialized. |
171 | /// |
172 | /// # Panics |
173 | /// |
174 | /// If `f()` panics, the panic is propagated to the caller, and the cell |
175 | /// remains uninitialized. |
176 | /// |
177 | /// # Examples |
178 | /// |
179 | /// ``` |
180 | /// #![feature(once_cell_get_mut)] |
181 | /// |
182 | /// use std::cell::OnceCell; |
183 | /// |
184 | /// let mut cell = OnceCell::new(); |
185 | /// let value = cell.get_mut_or_init(|| 92); |
186 | /// assert_eq!(*value, 92); |
187 | /// |
188 | /// *value += 2; |
189 | /// assert_eq!(*value, 94); |
190 | /// |
191 | /// let value = cell.get_mut_or_init(|| unreachable!()); |
192 | /// assert_eq!(*value, 94); |
193 | /// ``` |
194 | #[inline ] |
195 | #[unstable (feature = "once_cell_get_mut" , issue = "121641" )] |
196 | pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T |
197 | where |
198 | F: FnOnce() -> T, |
199 | { |
200 | match self.get_mut_or_try_init(|| Ok::<T, !>(f())) { |
201 | Ok(val) => val, |
202 | } |
203 | } |
204 | |
205 | /// Gets the contents of the cell, initializing it to `f()` if |
206 | /// the cell was uninitialized. If the cell was uninitialized |
207 | /// and `f()` failed, an error is returned. |
208 | /// |
209 | /// # Panics |
210 | /// |
211 | /// If `f()` panics, the panic is propagated to the caller, and the cell |
212 | /// remains uninitialized. |
213 | /// |
214 | /// It is an error to reentrantly initialize the cell from `f`. Doing |
215 | /// so results in a panic. |
216 | /// |
217 | /// # Examples |
218 | /// |
219 | /// ``` |
220 | /// #![feature(once_cell_try)] |
221 | /// |
222 | /// use std::cell::OnceCell; |
223 | /// |
224 | /// let cell = OnceCell::new(); |
225 | /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); |
226 | /// assert!(cell.get().is_none()); |
227 | /// let value = cell.get_or_try_init(|| -> Result<i32, ()> { |
228 | /// Ok(92) |
229 | /// }); |
230 | /// assert_eq!(value, Ok(&92)); |
231 | /// assert_eq!(cell.get(), Some(&92)) |
232 | /// ``` |
233 | #[unstable (feature = "once_cell_try" , issue = "109737" )] |
234 | pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> |
235 | where |
236 | F: FnOnce() -> Result<T, E>, |
237 | { |
238 | if let Some(val) = self.get() { |
239 | return Ok(val); |
240 | } |
241 | self.try_init(f) |
242 | } |
243 | |
244 | /// Gets the mutable reference of the contents of the cell, initializing |
245 | /// it to `f()` if the cell was uninitialized. If the cell was uninitialized |
246 | /// and `f()` failed, an error is returned. |
247 | /// |
248 | /// # Panics |
249 | /// |
250 | /// If `f()` panics, the panic is propagated to the caller, and the cell |
251 | /// remains uninitialized. |
252 | /// |
253 | /// # Examples |
254 | /// |
255 | /// ``` |
256 | /// #![feature(once_cell_get_mut)] |
257 | /// |
258 | /// use std::cell::OnceCell; |
259 | /// |
260 | /// let mut cell: OnceCell<u32> = OnceCell::new(); |
261 | /// |
262 | /// // Failed attempts to initialize the cell do not change its contents |
263 | /// assert!(cell.get_mut_or_try_init(|| "not a number!" .parse()).is_err()); |
264 | /// assert!(cell.get().is_none()); |
265 | /// |
266 | /// let value = cell.get_mut_or_try_init(|| "1234" .parse()); |
267 | /// assert_eq!(value, Ok(&mut 1234)); |
268 | /// |
269 | /// let Ok(value) = value else { return; }; |
270 | /// *value += 2; |
271 | /// assert_eq!(cell.get(), Some(&1236)) |
272 | /// ``` |
273 | #[unstable (feature = "once_cell_get_mut" , issue = "121641" )] |
274 | pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E> |
275 | where |
276 | F: FnOnce() -> Result<T, E>, |
277 | { |
278 | if self.get().is_none() { |
279 | self.try_init(f)?; |
280 | } |
281 | Ok(self.get_mut().unwrap()) |
282 | } |
283 | |
284 | // Avoid inlining the initialization closure into the common path that fetches |
285 | // the already initialized value |
286 | #[cold ] |
287 | fn try_init<F, E>(&self, f: F) -> Result<&T, E> |
288 | where |
289 | F: FnOnce() -> Result<T, E>, |
290 | { |
291 | let val = f()?; |
292 | // Note that *some* forms of reentrant initialization might lead to |
293 | // UB (see `reentrant_init` test). I believe that just removing this |
294 | // `panic`, while keeping `try_insert` would be sound, but it seems |
295 | // better to panic, rather than to silently use an old value. |
296 | if let Ok(val) = self.try_insert(val) { Ok(val) } else { panic!("reentrant init" ) } |
297 | } |
298 | |
299 | /// Consumes the cell, returning the wrapped value. |
300 | /// |
301 | /// Returns `None` if the cell was uninitialized. |
302 | /// |
303 | /// # Examples |
304 | /// |
305 | /// ``` |
306 | /// use std::cell::OnceCell; |
307 | /// |
308 | /// let cell: OnceCell<String> = OnceCell::new(); |
309 | /// assert_eq!(cell.into_inner(), None); |
310 | /// |
311 | /// let cell = OnceCell::new(); |
312 | /// let _ = cell.set("hello" .to_owned()); |
313 | /// assert_eq!(cell.into_inner(), Some("hello" .to_owned())); |
314 | /// ``` |
315 | #[inline ] |
316 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
317 | #[rustc_const_stable (feature = "const_cell_into_inner" , since = "1.83.0" )] |
318 | #[rustc_allow_const_fn_unstable (const_precise_live_drops)] |
319 | pub const fn into_inner(self) -> Option<T> { |
320 | // Because `into_inner` takes `self` by value, the compiler statically verifies |
321 | // that it is not currently borrowed. So it is safe to move out `Option<T>`. |
322 | self.inner.into_inner() |
323 | } |
324 | |
325 | /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. |
326 | /// |
327 | /// Has no effect and returns `None` if the `OnceCell` is uninitialized. |
328 | /// |
329 | /// Safety is guaranteed by requiring a mutable reference. |
330 | /// |
331 | /// # Examples |
332 | /// |
333 | /// ``` |
334 | /// use std::cell::OnceCell; |
335 | /// |
336 | /// let mut cell: OnceCell<String> = OnceCell::new(); |
337 | /// assert_eq!(cell.take(), None); |
338 | /// |
339 | /// let mut cell = OnceCell::new(); |
340 | /// let _ = cell.set("hello" .to_owned()); |
341 | /// assert_eq!(cell.take(), Some("hello" .to_owned())); |
342 | /// assert_eq!(cell.get(), None); |
343 | /// ``` |
344 | #[inline ] |
345 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
346 | pub fn take(&mut self) -> Option<T> { |
347 | mem::take(self).into_inner() |
348 | } |
349 | } |
350 | |
351 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
352 | impl<T> Default for OnceCell<T> { |
353 | #[inline ] |
354 | fn default() -> Self { |
355 | Self::new() |
356 | } |
357 | } |
358 | |
359 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
360 | impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { |
361 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
362 | let mut d: DebugTuple<'_, '_> = f.debug_tuple(name:"OnceCell" ); |
363 | match self.get() { |
364 | Some(v: &T) => d.field(v), |
365 | None => d.field(&format_args!("<uninit>" )), |
366 | }; |
367 | d.finish() |
368 | } |
369 | } |
370 | |
371 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
372 | impl<T: Clone> Clone for OnceCell<T> { |
373 | #[inline ] |
374 | fn clone(&self) -> OnceCell<T> { |
375 | let res: OnceCell = OnceCell::new(); |
376 | if let Some(value: &T) = self.get() { |
377 | match res.set(value.clone()) { |
378 | Ok(()) => (), |
379 | Err(_) => unreachable!(), |
380 | } |
381 | } |
382 | res |
383 | } |
384 | } |
385 | |
386 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
387 | impl<T: PartialEq> PartialEq for OnceCell<T> { |
388 | #[inline ] |
389 | fn eq(&self, other: &Self) -> bool { |
390 | self.get() == other.get() |
391 | } |
392 | } |
393 | |
394 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
395 | impl<T: Eq> Eq for OnceCell<T> {} |
396 | |
397 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
398 | impl<T> From<T> for OnceCell<T> { |
399 | /// Creates a new `OnceCell<T>` which already contains the given `value`. |
400 | #[inline ] |
401 | fn from(value: T) -> Self { |
402 | OnceCell { inner: UnsafeCell::new(Some(value)) } |
403 | } |
404 | } |
405 | |
406 | // Just like for `Cell<T>` this isn't needed, but results in nicer error messages. |
407 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
408 | impl<T> !Sync for OnceCell<T> {} |
409 | |