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