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