1 | //! Defines [`Exclusive`]. |
2 | |
3 | use core::fmt; |
4 | use core::future::Future; |
5 | use core::marker::Tuple; |
6 | use core::ops::{Coroutine, CoroutineState}; |
7 | use core::pin::Pin; |
8 | use core::task::{Context, Poll}; |
9 | |
10 | /// `Exclusive` provides only _mutable_ access, also referred to as _exclusive_ |
11 | /// access to the underlying value. It provides no _immutable_, or _shared_ |
12 | /// access to the underlying value. |
13 | /// |
14 | /// While this may seem not very useful, it allows `Exclusive` to _unconditionally_ |
15 | /// implement [`Sync`]. Indeed, the safety requirements of `Sync` state that for `Exclusive` |
16 | /// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound |
17 | /// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive` has no API |
18 | /// whatsoever, making it useless, thus harmless, thus memory safe. |
19 | /// |
20 | /// Certain constructs like [`Future`]s can only be used with _exclusive_ access, |
21 | /// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the |
22 | /// Rust compiler that something is `Sync` in practice. |
23 | /// |
24 | /// ## Examples |
25 | /// Using a non-`Sync` future prevents the wrapping struct from being `Sync` |
26 | /// ```compile_fail |
27 | /// use core::cell::Cell; |
28 | /// |
29 | /// async fn other() {} |
30 | /// fn assert_sync<T: Sync>(t: T) {} |
31 | /// struct State<F> { |
32 | /// future: F |
33 | /// } |
34 | /// |
35 | /// assert_sync(State { |
36 | /// future: async { |
37 | /// let cell = Cell::new(1); |
38 | /// let cell_ref = &cell; |
39 | /// other().await; |
40 | /// let value = cell_ref.get(); |
41 | /// } |
42 | /// }); |
43 | /// ``` |
44 | /// |
45 | /// `Exclusive` ensures the struct is `Sync` without stripping the future of its |
46 | /// functionality. |
47 | /// ``` |
48 | /// #![feature(exclusive_wrapper)] |
49 | /// use core::cell::Cell; |
50 | /// use core::sync::Exclusive; |
51 | /// |
52 | /// async fn other() {} |
53 | /// fn assert_sync<T: Sync>(t: T) {} |
54 | /// struct State<F> { |
55 | /// future: Exclusive<F> |
56 | /// } |
57 | /// |
58 | /// assert_sync(State { |
59 | /// future: Exclusive::new(async { |
60 | /// let cell = Cell::new(1); |
61 | /// let cell_ref = &cell; |
62 | /// other().await; |
63 | /// let value = cell_ref.get(); |
64 | /// }) |
65 | /// }); |
66 | /// ``` |
67 | /// |
68 | /// ## Parallels with a mutex |
69 | /// In some sense, `Exclusive` can be thought of as a _compile-time_ version of |
70 | /// a mutex, as the borrow-checker guarantees that only one `&mut` can exist |
71 | /// for any value. This is a parallel with the fact that |
72 | /// `&` and `&mut` references together can be thought of as a _compile-time_ |
73 | /// version of a read-write lock. |
74 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
75 | #[doc (alias = "SyncWrapper" )] |
76 | #[doc (alias = "SyncCell" )] |
77 | #[doc (alias = "Unique" )] |
78 | // `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would |
79 | // use `&` access to the inner value, violating the `Sync` impl's safety |
80 | // requirements. |
81 | #[derive (Default)] |
82 | #[repr (transparent)] |
83 | pub struct Exclusive<T: ?Sized> { |
84 | inner: T, |
85 | } |
86 | |
87 | // See `Exclusive`'s docs for justification. |
88 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
89 | unsafe impl<T: ?Sized> Sync for Exclusive<T> {} |
90 | |
91 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
92 | impl<T: ?Sized> fmt::Debug for Exclusive<T> { |
93 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
94 | f.debug_struct(name:"Exclusive" ).finish_non_exhaustive() |
95 | } |
96 | } |
97 | |
98 | impl<T: Sized> Exclusive<T> { |
99 | /// Wrap a value in an `Exclusive` |
100 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
101 | #[must_use ] |
102 | #[inline ] |
103 | pub const fn new(t: T) -> Self { |
104 | Self { inner: t } |
105 | } |
106 | |
107 | /// Unwrap the value contained in the `Exclusive` |
108 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
109 | #[rustc_const_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 | /// Gets 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 | /// Gets 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_ reference 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_ reference 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<F, Args> FnOnce<Args> for Exclusive<F> |
175 | where |
176 | F: FnOnce<Args>, |
177 | Args: Tuple, |
178 | { |
179 | type Output = F::Output; |
180 | |
181 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output { |
182 | self.into_inner().call_once(args) |
183 | } |
184 | } |
185 | |
186 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
187 | impl<F, Args> FnMut<Args> for Exclusive<F> |
188 | where |
189 | F: FnMut<Args>, |
190 | Args: Tuple, |
191 | { |
192 | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { |
193 | self.get_mut().call_mut(args) |
194 | } |
195 | } |
196 | |
197 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
198 | impl<T> Future for Exclusive<T> |
199 | where |
200 | T: Future + ?Sized, |
201 | { |
202 | type Output = T::Output; |
203 | |
204 | #[inline ] |
205 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
206 | self.get_pin_mut().poll(cx) |
207 | } |
208 | } |
209 | |
210 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] // also #98407 |
211 | impl<R, G> Coroutine<R> for Exclusive<G> |
212 | where |
213 | G: Coroutine<R> + ?Sized, |
214 | { |
215 | type Yield = G::Yield; |
216 | type Return = G::Return; |
217 | |
218 | #[inline ] |
219 | fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> { |
220 | G::resume(self.get_pin_mut(), arg) |
221 | } |
222 | } |
223 | |