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