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 contents of the cell, initializing it with `f` if |
168 | /// the cell was empty. If the cell was empty and `f` failed, an |
169 | /// error is returned. |
170 | /// |
171 | /// # Panics |
172 | /// |
173 | /// If `f` panics, the panic is propagated to the caller, and the cell |
174 | /// remains uninitialized. |
175 | /// |
176 | /// It is an error to reentrantly initialize the cell from `f`. Doing |
177 | /// so results in a panic. |
178 | /// |
179 | /// # Examples |
180 | /// |
181 | /// ``` |
182 | /// #![feature(once_cell_try)] |
183 | /// |
184 | /// use std::cell::OnceCell; |
185 | /// |
186 | /// let cell = OnceCell::new(); |
187 | /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); |
188 | /// assert!(cell.get().is_none()); |
189 | /// let value = cell.get_or_try_init(|| -> Result<i32, ()> { |
190 | /// Ok(92) |
191 | /// }); |
192 | /// assert_eq!(value, Ok(&92)); |
193 | /// assert_eq!(cell.get(), Some(&92)) |
194 | /// ``` |
195 | #[unstable (feature = "once_cell_try" , issue = "109737" )] |
196 | pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> |
197 | where |
198 | F: FnOnce() -> Result<T, E>, |
199 | { |
200 | if let Some(val) = self.get() { |
201 | return Ok(val); |
202 | } |
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() |
211 | } |
212 | let val = outlined_call(f)?; |
213 | // Note that *some* forms of reentrant initialization might lead to |
214 | // UB (see `reentrant_init` test). I believe that just removing this |
215 | // `panic`, while keeping `try_insert` would be sound, but it seems |
216 | // better to panic, rather than to silently use an old value. |
217 | if let Ok(val) = self.try_insert(val) { Ok(val) } else { panic!("reentrant init" ) } |
218 | } |
219 | |
220 | /// Consumes the cell, returning the wrapped value. |
221 | /// |
222 | /// Returns `None` if the cell was empty. |
223 | /// |
224 | /// # Examples |
225 | /// |
226 | /// ``` |
227 | /// use std::cell::OnceCell; |
228 | /// |
229 | /// let cell: OnceCell<String> = OnceCell::new(); |
230 | /// assert_eq!(cell.into_inner(), None); |
231 | /// |
232 | /// let cell = OnceCell::new(); |
233 | /// cell.set("hello" .to_string()).unwrap(); |
234 | /// assert_eq!(cell.into_inner(), Some("hello" .to_string())); |
235 | /// ``` |
236 | #[inline ] |
237 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
238 | pub fn into_inner(self) -> Option<T> { |
239 | // Because `into_inner` takes `self` by value, the compiler statically verifies |
240 | // that it is not currently borrowed. So it is safe to move out `Option<T>`. |
241 | self.inner.into_inner() |
242 | } |
243 | |
244 | /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. |
245 | /// |
246 | /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. |
247 | /// |
248 | /// Safety is guaranteed by requiring a mutable reference. |
249 | /// |
250 | /// # Examples |
251 | /// |
252 | /// ``` |
253 | /// use std::cell::OnceCell; |
254 | /// |
255 | /// let mut cell: OnceCell<String> = OnceCell::new(); |
256 | /// assert_eq!(cell.take(), None); |
257 | /// |
258 | /// let mut cell = OnceCell::new(); |
259 | /// cell.set("hello" .to_string()).unwrap(); |
260 | /// assert_eq!(cell.take(), Some("hello" .to_string())); |
261 | /// assert_eq!(cell.get(), None); |
262 | /// ``` |
263 | #[inline ] |
264 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
265 | pub fn take(&mut self) -> Option<T> { |
266 | mem::take(self).into_inner() |
267 | } |
268 | } |
269 | |
270 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
271 | impl<T> Default for OnceCell<T> { |
272 | #[inline ] |
273 | fn default() -> Self { |
274 | Self::new() |
275 | } |
276 | } |
277 | |
278 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
279 | impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { |
280 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
281 | let mut d: DebugTuple<'_, '_> = f.debug_tuple(name:"OnceCell" ); |
282 | match self.get() { |
283 | Some(v: &T) => d.field(v), |
284 | None => d.field(&format_args!("<uninit>" )), |
285 | }; |
286 | d.finish() |
287 | } |
288 | } |
289 | |
290 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
291 | impl<T: Clone> Clone for OnceCell<T> { |
292 | #[inline ] |
293 | fn clone(&self) -> OnceCell<T> { |
294 | let res: OnceCell = OnceCell::new(); |
295 | if let Some(value: &T) = self.get() { |
296 | match res.set(value.clone()) { |
297 | Ok(()) => (), |
298 | Err(_) => unreachable!(), |
299 | } |
300 | } |
301 | res |
302 | } |
303 | } |
304 | |
305 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
306 | impl<T: PartialEq> PartialEq for OnceCell<T> { |
307 | #[inline ] |
308 | fn eq(&self, other: &Self) -> bool { |
309 | self.get() == other.get() |
310 | } |
311 | } |
312 | |
313 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
314 | impl<T: Eq> Eq for OnceCell<T> {} |
315 | |
316 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
317 | impl<T> From<T> for OnceCell<T> { |
318 | /// Creates a new `OnceCell<T>` which already contains the given `value`. |
319 | #[inline ] |
320 | fn from(value: T) -> Self { |
321 | OnceCell { inner: UnsafeCell::new(Some(value)) } |
322 | } |
323 | } |
324 | |
325 | // Just like for `Cell<T>` this isn't needed, but results in nicer error messages. |
326 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
327 | impl<T> !Sync for OnceCell<T> {} |
328 | |