]> git.lizzy.rs Git - rust.git/blob - library/core/src/sync/exclusive.rs
Rollup merge of #103276 - compiler-errors:default-on-uninit-ice, r=TaKO8Ki
[rust.git] / library / core / src / sync / exclusive.rs
1 //! Defines [`Exclusive`].
2
3 use core::fmt;
4 use core::future::Future;
5 use core::pin::Pin;
6 use core::task::{Context, Poll};
7
8 /// `Exclusive` provides only _mutable_ access, also referred to as _exclusive_
9 /// access to the underlying value. It provides no _immutable_, or _shared_
10 /// access to the underlying value.
11 ///
12 /// While this may seem not very useful, it allows `Exclusive` to _unconditionally_
13 /// implement [`Sync`]. Indeed, the safety requirements of `Sync` state that for `Exclusive`
14 /// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound
15 /// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive` has no API
16 /// whatsoever, making it useless, thus harmless, thus memory safe.
17 ///
18 /// Certain constructs like [`Future`]s can only be used with _exclusive_ access,
19 /// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the
20 /// rust compiler that something is `Sync` in practice.
21 ///
22 /// ## Examples
23 /// Using a non-`Sync` future prevents the wrapping struct from being `Sync`
24 /// ```compile_fail
25 /// use core::cell::Cell;
26 ///
27 /// async fn other() {}
28 /// fn assert_sync<T: Sync>(t: T) {}
29 /// struct State<F> {
30 ///     future: F
31 /// }
32 ///
33 /// assert_sync(State {
34 ///     future: async {
35 ///         let cell = Cell::new(1);
36 ///         let cell_ref = &cell;
37 ///         other().await;
38 ///         let value = cell_ref.get();
39 ///     }
40 /// });
41 /// ```
42 ///
43 /// `Exclusive` ensures the struct is `Sync` without stripping the future of its
44 /// functionality.
45 /// ```
46 /// #![feature(exclusive_wrapper)]
47 /// use core::cell::Cell;
48 /// use core::sync::Exclusive;
49 ///
50 /// async fn other() {}
51 /// fn assert_sync<T: Sync>(t: T) {}
52 /// struct State<F> {
53 ///     future: Exclusive<F>
54 /// }
55 ///
56 /// assert_sync(State {
57 ///     future: Exclusive::new(async {
58 ///         let cell = Cell::new(1);
59 ///         let cell_ref = &cell;
60 ///         other().await;
61 ///         let value = cell_ref.get();
62 ///     })
63 /// });
64 /// ```
65 ///
66 /// ## Parallels with a mutex
67 /// In some sense, `Exclusive` can be thought of as a _compile-time_ version of
68 /// a mutex, as the borrow-checker guarantees that only one `&mut` can exist
69 /// for any value. This is a parallel with the fact that
70 /// `&` and `&mut` references together can be thought of as a _compile-time_
71 /// version of a read-write lock.
72 ///
73 ///
74 /// [`Sync`]: core::marker::Sync
75 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
76 #[doc(alias = "SyncWrapper")]
77 #[doc(alias = "SyncCell")]
78 #[doc(alias = "Unique")]
79 // `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would
80 // use `&` access to the inner value, violating the `Sync` impl's safety
81 // requirements.
82 #[derive(Default)]
83 #[repr(transparent)]
84 pub struct Exclusive<T: ?Sized> {
85     inner: T,
86 }
87
88 // See `Exclusive`'s docs for justification.
89 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
90 unsafe impl<T: ?Sized> Sync for Exclusive<T> {}
91
92 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
93 impl<T: ?Sized> fmt::Debug for Exclusive<T> {
94     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
95         f.debug_struct("Exclusive").finish_non_exhaustive()
96     }
97 }
98
99 impl<T: Sized> Exclusive<T> {
100     /// Wrap a value in an `Exclusive`
101     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
102     #[must_use]
103     #[inline]
104     pub const fn new(t: T) -> Self {
105         Self { inner: t }
106     }
107
108     /// Unwrap the value contained in the `Exclusive`
109     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
110     #[must_use]
111     #[inline]
112     pub const fn into_inner(self) -> T {
113         self.inner
114     }
115 }
116
117 impl<T: ?Sized> Exclusive<T> {
118     /// Get exclusive access to the underlying value.
119     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
120     #[must_use]
121     #[inline]
122     pub const fn get_mut(&mut self) -> &mut T {
123         &mut self.inner
124     }
125
126     /// Get pinned exclusive access to the underlying value.
127     ///
128     /// `Exclusive` is considered to _structurally pin_ the underlying
129     /// value, which means _unpinned_ `Exclusive`s can produce _unpinned_
130     /// access to the underlying value, but _pinned_ `Exclusive`s only
131     /// produce _pinned_ access to the underlying value.
132     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
133     #[must_use]
134     #[inline]
135     pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
136         // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
137         // `Pin::map_unchecked_mut` is not const, so we do this conversion manually
138         unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
139     }
140
141     /// Build a _mutable_ references to an `Exclusive<T>` from
142     /// a _mutable_ reference to a `T`. This allows you to skip
143     /// building an `Exclusive` with [`Exclusive::new`].
144     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
145     #[must_use]
146     #[inline]
147     pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> {
148         // SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic
149         unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
150     }
151
152     /// Build a _pinned mutable_ references to an `Exclusive<T>` from
153     /// a _pinned mutable_ reference to a `T`. This allows you to skip
154     /// building an `Exclusive` with [`Exclusive::new`].
155     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
156     #[must_use]
157     #[inline]
158     pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> {
159         // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
160         // `Pin::map_unchecked_mut` is not const, so we do this conversion manually
161         unsafe { Pin::new_unchecked(Self::from_mut(r.get_unchecked_mut())) }
162     }
163 }
164
165 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
166 impl<T> From<T> for Exclusive<T> {
167     #[inline]
168     fn from(t: T) -> Self {
169         Self::new(t)
170     }
171 }
172
173 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
174 impl<T: Future + ?Sized> Future for Exclusive<T> {
175     type Output = T::Output;
176     #[inline]
177     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
178         self.get_pin_mut().poll(cx)
179     }
180 }