]> git.lizzy.rs Git - rust.git/blob - library/core/src/cell/once.rs
Auto merge of #97235 - nbdd0121:unwind, r=Amanieu
[rust.git] / library / core / src / cell / once.rs
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 /// Unlike `RefCell`, a `OnceCell` only provides shared `&T` references to its value.
8 /// Unlike `Cell`, a `OnceCell` doesn't require copying or replacing the value to access it.
9 ///
10 /// # Examples
11 ///
12 /// ```
13 /// #![feature(once_cell)]
14 ///
15 /// use std::cell::OnceCell;
16 ///
17 /// let cell = OnceCell::new();
18 /// assert!(cell.get().is_none());
19 ///
20 /// let value: &String = cell.get_or_init(|| {
21 ///     "Hello, World!".to_string()
22 /// });
23 /// assert_eq!(value, "Hello, World!");
24 /// assert!(cell.get().is_some());
25 /// ```
26 #[unstable(feature = "once_cell", issue = "74465")]
27 pub struct OnceCell<T> {
28     // Invariant: written to at most once.
29     inner: UnsafeCell<Option<T>>,
30 }
31
32 impl<T> OnceCell<T> {
33     /// Creates a new empty cell.
34     #[unstable(feature = "once_cell", issue = "74465")]
35     #[must_use]
36     pub const fn new() -> OnceCell<T> {
37         OnceCell { inner: UnsafeCell::new(None) }
38     }
39
40     /// Gets the reference to the underlying value.
41     ///
42     /// Returns `None` if the cell is empty.
43     #[unstable(feature = "once_cell", issue = "74465")]
44     pub fn get(&self) -> Option<&T> {
45         // SAFETY: Safe due to `inner`'s invariant
46         unsafe { &*self.inner.get() }.as_ref()
47     }
48
49     /// Gets the mutable reference to the underlying value.
50     ///
51     /// Returns `None` if the cell is empty.
52     #[unstable(feature = "once_cell", issue = "74465")]
53     pub fn get_mut(&mut self) -> Option<&mut T> {
54         self.inner.get_mut().as_mut()
55     }
56
57     /// Sets the contents of the cell to `value`.
58     ///
59     /// # Errors
60     ///
61     /// This method returns `Ok(())` if the cell was empty and `Err(value)` if
62     /// it was full.
63     ///
64     /// # Examples
65     ///
66     /// ```
67     /// #![feature(once_cell)]
68     ///
69     /// use std::cell::OnceCell;
70     ///
71     /// let cell = OnceCell::new();
72     /// assert!(cell.get().is_none());
73     ///
74     /// assert_eq!(cell.set(92), Ok(()));
75     /// assert_eq!(cell.set(62), Err(62));
76     ///
77     /// assert!(cell.get().is_some());
78     /// ```
79     #[unstable(feature = "once_cell", issue = "74465")]
80     pub fn set(&self, value: T) -> Result<(), T> {
81         // SAFETY: Safe because we cannot have overlapping mutable borrows
82         let slot = unsafe { &*self.inner.get() };
83         if slot.is_some() {
84             return Err(value);
85         }
86
87         // SAFETY: This is the only place where we set the slot, no races
88         // due to reentrancy/concurrency are possible, and we've
89         // checked that slot is currently `None`, so this write
90         // maintains the `inner`'s invariant.
91         let slot = unsafe { &mut *self.inner.get() };
92         *slot = Some(value);
93         Ok(())
94     }
95
96     /// Gets the contents of the cell, initializing it with `f`
97     /// if the cell was empty.
98     ///
99     /// # Panics
100     ///
101     /// If `f` panics, the panic is propagated to the caller, and the cell
102     /// remains uninitialized.
103     ///
104     /// It is an error to reentrantly initialize the cell from `f`. Doing
105     /// so results in a panic.
106     ///
107     /// # Examples
108     ///
109     /// ```
110     /// #![feature(once_cell)]
111     ///
112     /// use std::cell::OnceCell;
113     ///
114     /// let cell = OnceCell::new();
115     /// let value = cell.get_or_init(|| 92);
116     /// assert_eq!(value, &92);
117     /// let value = cell.get_or_init(|| unreachable!());
118     /// assert_eq!(value, &92);
119     /// ```
120     #[unstable(feature = "once_cell", issue = "74465")]
121     pub fn get_or_init<F>(&self, f: F) -> &T
122     where
123         F: FnOnce() -> T,
124     {
125         match self.get_or_try_init(|| Ok::<T, !>(f())) {
126             Ok(val) => val,
127         }
128     }
129
130     /// Gets the contents of the cell, initializing it with `f` if
131     /// the cell was empty. If the cell was empty and `f` failed, an
132     /// error is returned.
133     ///
134     /// # Panics
135     ///
136     /// If `f` panics, the panic is propagated to the caller, and the cell
137     /// remains uninitialized.
138     ///
139     /// It is an error to reentrantly initialize the cell from `f`. Doing
140     /// so results in a panic.
141     ///
142     /// # Examples
143     ///
144     /// ```
145     /// #![feature(once_cell)]
146     ///
147     /// use std::cell::OnceCell;
148     ///
149     /// let cell = OnceCell::new();
150     /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
151     /// assert!(cell.get().is_none());
152     /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
153     ///     Ok(92)
154     /// });
155     /// assert_eq!(value, Ok(&92));
156     /// assert_eq!(cell.get(), Some(&92))
157     /// ```
158     #[unstable(feature = "once_cell", issue = "74465")]
159     pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
160     where
161         F: FnOnce() -> Result<T, E>,
162     {
163         if let Some(val) = self.get() {
164             return Ok(val);
165         }
166         /// Avoid inlining the initialization closure into the common path that fetches
167         /// the already initialized value
168         #[cold]
169         fn outlined_call<F, T, E>(f: F) -> Result<T, E>
170         where
171             F: FnOnce() -> Result<T, E>,
172         {
173             f()
174         }
175         let val = outlined_call(f)?;
176         // Note that *some* forms of reentrant initialization might lead to
177         // UB (see `reentrant_init` test). I believe that just removing this
178         // `assert`, while keeping `set/get` would be sound, but it seems
179         // better to panic, rather than to silently use an old value.
180         assert!(self.set(val).is_ok(), "reentrant init");
181         Ok(self.get().unwrap())
182     }
183
184     /// Consumes the cell, returning the wrapped value.
185     ///
186     /// Returns `None` if the cell was empty.
187     ///
188     /// # Examples
189     ///
190     /// ```
191     /// #![feature(once_cell)]
192     ///
193     /// use std::cell::OnceCell;
194     ///
195     /// let cell: OnceCell<String> = OnceCell::new();
196     /// assert_eq!(cell.into_inner(), None);
197     ///
198     /// let cell = OnceCell::new();
199     /// cell.set("hello".to_string()).unwrap();
200     /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
201     /// ```
202     #[unstable(feature = "once_cell", issue = "74465")]
203     pub fn into_inner(self) -> Option<T> {
204         // Because `into_inner` takes `self` by value, the compiler statically verifies
205         // that it is not currently borrowed. So it is safe to move out `Option<T>`.
206         self.inner.into_inner()
207     }
208
209     /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
210     ///
211     /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
212     ///
213     /// Safety is guaranteed by requiring a mutable reference.
214     ///
215     /// # Examples
216     ///
217     /// ```
218     /// #![feature(once_cell)]
219     ///
220     /// use std::cell::OnceCell;
221     ///
222     /// let mut cell: OnceCell<String> = OnceCell::new();
223     /// assert_eq!(cell.take(), None);
224     ///
225     /// let mut cell = OnceCell::new();
226     /// cell.set("hello".to_string()).unwrap();
227     /// assert_eq!(cell.take(), Some("hello".to_string()));
228     /// assert_eq!(cell.get(), None);
229     /// ```
230     #[unstable(feature = "once_cell", issue = "74465")]
231     pub fn take(&mut self) -> Option<T> {
232         mem::take(self).into_inner()
233     }
234 }
235
236 #[unstable(feature = "once_cell", issue = "74465")]
237 impl<T> Default for OnceCell<T> {
238     fn default() -> Self {
239         Self::new()
240     }
241 }
242
243 #[unstable(feature = "once_cell", issue = "74465")]
244 impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
245     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246         match self.get() {
247             Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
248             None => f.write_str("OnceCell(Uninit)"),
249         }
250     }
251 }
252
253 #[unstable(feature = "once_cell", issue = "74465")]
254 impl<T: Clone> Clone for OnceCell<T> {
255     fn clone(&self) -> OnceCell<T> {
256         let res = OnceCell::new();
257         if let Some(value) = self.get() {
258             match res.set(value.clone()) {
259                 Ok(()) => (),
260                 Err(_) => unreachable!(),
261             }
262         }
263         res
264     }
265 }
266
267 #[unstable(feature = "once_cell", issue = "74465")]
268 impl<T: PartialEq> PartialEq for OnceCell<T> {
269     fn eq(&self, other: &Self) -> bool {
270         self.get() == other.get()
271     }
272 }
273
274 #[unstable(feature = "once_cell", issue = "74465")]
275 impl<T: Eq> Eq for OnceCell<T> {}
276
277 #[unstable(feature = "once_cell", issue = "74465")]
278 impl<T> const From<T> for OnceCell<T> {
279     /// Creates a new `OnceCell<T>` which already contains the given `value`.
280     fn from(value: T) -> Self {
281         OnceCell { inner: UnsafeCell::new(Some(value)) }
282     }
283 }