Skip to main content

core/sync/
sync_view.rs

1//! Defines [`SyncView`].
2
3use core::clone::TrivialClone;
4use core::cmp::Ordering;
5use core::fmt;
6use core::future::Future;
7use core::hash::{Hash, Hasher};
8use core::marker::{StructuralPartialEq, Tuple};
9use core::ops::{Coroutine, CoroutineState};
10use core::pin::Pin;
11use core::task::{Context, Poll};
12
13/// `SyncView` provides _mutable_ access, also referred to as _exclusive_
14/// access to the underlying value. However, it only permits _immutable_, or _shared_
15/// access to the underlying value when that value is [`Sync`].
16///
17/// While this may seem not very useful, it allows `SyncView` to _unconditionally_
18/// implement `Sync`. Indeed, the safety requirements of `Sync` state that for `SyncView`
19/// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound
20/// for `&SyncView` to cross thread boundaries. By design, a `&SyncView<T>` for non-`Sync`
21/// `T` has no API whatsoever, making it useless, thus harmless, thus memory safe.
22///
23/// Certain constructs like [`Future`]s can only be used with _exclusive_ access,
24/// and are often [`Send`] but not `Sync`, so `SyncView` can be used as hint to the
25/// Rust compiler that something is `Sync` in practice.
26///
27/// ## Examples
28///
29/// A non-`Sync` field prevents the wrapping struct from being `Sync`:
30///
31/// ```compile_fail,E0277
32/// use std::sync::mpsc::{self, Receiver};
33///
34/// struct Inbox {
35///     name: &'static str,
36///     receiver: Receiver<u32>,
37/// }
38///
39/// fn require_send<T: Send>() {}
40/// fn require_send_sync<T: Send + Sync>() {}
41///
42/// require_send::<Inbox>();      // compiled
43/// require_send_sync::<Inbox>(); // compile-failed
44/// ```
45///
46/// `SyncView` makes the value `Sync` without stripping the struct of its
47/// functionality:
48///
49/// ```ignore-wasm
50/// use std::sync::SyncView;
51/// use std::sync::mpsc::{self, Receiver};
52/// use std::thread;
53///
54/// struct Inbox {
55///     name: &'static str,
56///     receiver: SyncView<Receiver<u32>>,
57/// }
58///
59/// impl Inbox {
60///     fn name(&self) -> &'static str {
61///         self.name
62///     }
63///
64///     fn recv(&mut self) -> u32 {
65///         self.receiver.as_mut().recv().unwrap()
66///     }
67/// }
68///
69/// let (sender, receiver) = mpsc::channel();
70/// let mut inbox = Inbox { name: "jobs", receiver: SyncView::new(receiver) };
71/// sender.send(42).unwrap();
72/// drop(sender);
73///
74/// thread::scope(|scope| {
75///     let reader = scope.spawn(|| inbox.name());
76///     assert_eq!(inbox.name(), "jobs");
77///     assert_eq!(reader.join().unwrap(), "jobs");
78/// });
79///
80/// let message = thread::spawn(move || inbox.recv()).join().unwrap();
81/// assert_eq!(message, 42);
82/// println!("Shared Inbox across threads, then moved it to a worker and received 42");
83/// ```
84///
85/// ## Parallels with a mutex
86///
87/// In some sense, `SyncView` can be thought of as a _compile-time_ version of
88/// a mutex, as the borrow-checker guarantees that only one `&mut` can exist
89/// for any value. This is a parallel with the fact that
90/// `&` and `&mut` references together can be thought of as a _compile-time_
91/// version of a read-write lock.
92#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
93#[doc(alias = "SyncWrapper")]
94#[doc(alias = "SyncCell")]
95#[doc(alias = "Unique")]
96#[doc(alias = "Exclusive")]
97// `SyncView` can't have derived `PartialOrd`, `Clone`, etc. impls as they would
98// use `&` access to the inner value, violating the `Sync` impl's safety
99// requirements.
100#[repr(transparent)]
101pub struct SyncView<T: ?Sized> {
102    inner: T,
103}
104
105// See `SyncView`'s docs for justification.
106#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
107unsafe impl<T: ?Sized> Sync for SyncView<T> {}
108
109#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
110#[rustc_const_unstable(feature = "const_default", issue = "143894")]
111const impl<T> Default for SyncView<T>
112where
113    T: [const] Default,
114{
115    #[inline]
116    fn default() -> Self {
117        Self { inner: Default::default() }
118    }
119}
120
121#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
122impl<T: ?Sized> fmt::Debug for SyncView<T> {
123    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
124        f.debug_struct("SyncView").finish_non_exhaustive()
125    }
126}
127
128impl<T: Sized> SyncView<T> {
129    /// Wrap a value in an `SyncView`
130    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
131    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
132    #[must_use]
133    #[inline]
134    pub const fn new(t: T) -> Self {
135        Self { inner: t }
136    }
137
138    /// Unwrap the value contained in the `SyncView`
139    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
140    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
141    #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
142    #[must_use]
143    #[inline]
144    pub const fn into_inner(self) -> T {
145        self.inner
146    }
147}
148
149impl<T: ?Sized> SyncView<T> {
150    /// Gets pinned exclusive access to the underlying value.
151    ///
152    /// `SyncView` is considered to _structurally pin_ the underlying
153    /// value, which means _unpinned_ `SyncView`s can produce _unpinned_
154    /// access to the underlying value, but _pinned_ `SyncView`s only
155    /// produce _pinned_ access to the underlying value.
156    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
157    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
158    #[must_use]
159    #[inline]
160    pub const fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
161        // SAFETY: `SyncView` can only produce `&mut T` if itself is unpinned
162        // `Pin::map_unchecked_mut` is not const, so we do this conversion manually
163        unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
164    }
165
166    /// Build a _mutable_ reference to an `SyncView<T>` from
167    /// a _mutable_ reference to a `T`. This allows you to skip
168    /// building an `SyncView` with [`SyncView::new`].
169    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
170    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
171    #[must_use]
172    #[inline]
173    pub const fn from_mut(r: &'_ mut T) -> &'_ mut SyncView<T> {
174        // SAFETY: repr is ≥ C, so refs have the same layout; and `SyncView` properties are `&mut`-agnostic
175        unsafe { &mut *(r as *mut T as *mut SyncView<T>) }
176    }
177
178    /// Build a _pinned mutable_ reference to an `SyncView<T>` from
179    /// a _pinned mutable_ reference to a `T`. This allows you to skip
180    /// building an `SyncView` with [`SyncView::new`].
181    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
182    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
183    #[must_use]
184    #[inline]
185    pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut SyncView<T>> {
186        // SAFETY: `SyncView` can only produce `&mut T` if itself is unpinned
187        // `Pin::map_unchecked_mut` is not const, so we do this conversion manually
188        unsafe { Pin::new_unchecked(Self::from_mut(r.get_unchecked_mut())) }
189    }
190}
191
192impl<T: ?Sized + Sync> SyncView<T> {
193    /// Gets pinned shared access to the underlying value.
194    ///
195    /// `SyncView` is considered to _structurally pin_ the underlying
196    /// value, which means _unpinned_ `SyncView`s can produce _unpinned_
197    /// access to the underlying value, but _pinned_ `SyncView`s only
198    /// produce _pinned_ access to the underlying value.
199    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
200    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
201    #[must_use]
202    #[inline]
203    pub const fn as_pin_ref(self: Pin<&Self>) -> Pin<&T> {
204        // SAFETY: `SyncView` can only produce `&T` if itself is unpinned
205        // `Pin::map_unchecked` is not const, so we do this conversion manually
206        unsafe { Pin::new_unchecked(&self.get_ref().inner) }
207    }
208}
209
210#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
211#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
212const impl<T> From<T> for SyncView<T> {
213    #[inline]
214    fn from(t: T) -> Self {
215        Self::new(t)
216    }
217}
218
219#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
220#[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
221const impl<F, Args> FnOnce<Args> for SyncView<F>
222where
223    F: [const] FnOnce<Args>,
224    Args: Tuple,
225{
226    type Output = F::Output;
227
228    extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
229        self.into_inner().call_once(args)
230    }
231}
232
233#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
234#[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
235const impl<F, Args> FnMut<Args> for SyncView<F>
236where
237    F: [const] FnMut<Args>,
238    Args: Tuple,
239{
240    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
241        self.as_mut().call_mut(args)
242    }
243}
244
245#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
246#[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
247const impl<F, Args> Fn<Args> for SyncView<F>
248where
249    F: Sync + [const] Fn<Args>,
250    Args: Tuple,
251{
252    extern "rust-call" fn call(&self, args: Args) -> Self::Output {
253        self.as_ref().call(args)
254    }
255}
256
257#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
258impl<F, Args> AsyncFnOnce<Args> for SyncView<F>
259where
260    F: AsyncFnOnce<Args>,
261    Args: Tuple,
262{
263    type CallOnceFuture = F::CallOnceFuture;
264
265    type Output = F::Output;
266
267    extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture {
268        self.into_inner().async_call_once(args)
269    }
270}
271
272#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
273impl<F, Args> AsyncFnMut<Args> for SyncView<F>
274where
275    F: AsyncFnMut<Args>,
276    Args: Tuple,
277{
278    type CallRefFuture<'a>
279        = F::CallRefFuture<'a>
280    where
281        F: 'a;
282
283    extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_> {
284        self.as_mut().async_call_mut(args)
285    }
286}
287
288#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
289impl<F, Args> AsyncFn<Args> for SyncView<F>
290where
291    F: Sync + AsyncFn<Args>,
292    Args: Tuple,
293{
294    extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> {
295        self.as_ref().async_call(args)
296    }
297}
298
299#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
300impl<T> Future for SyncView<T>
301where
302    T: Future + ?Sized,
303{
304    type Output = T::Output;
305
306    #[inline]
307    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
308        self.as_pin_mut().poll(cx)
309    }
310}
311
312#[unstable(feature = "coroutine_trait", issue = "43122")] // also #98407
313impl<R, G> Coroutine<R> for SyncView<G>
314where
315    G: Coroutine<R> + ?Sized,
316{
317    type Yield = G::Yield;
318    type Return = G::Return;
319
320    #[inline]
321    fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
322        G::resume(self.as_pin_mut(), arg)
323    }
324}
325
326#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
327#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
328const impl<T> AsRef<T> for SyncView<T>
329where
330    T: Sync + ?Sized,
331{
332    /// Gets shared access to the underlying value.
333    #[inline]
334    fn as_ref(&self) -> &T {
335        &self.inner
336    }
337}
338
339#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
340#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
341const impl<T> AsMut<T> for SyncView<T>
342where
343    T: ?Sized,
344{
345    /// Gets exclusive access to the underlying value.
346    #[inline]
347    fn as_mut(&mut self) -> &mut T {
348        &mut self.inner
349    }
350}
351
352#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
353#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
354const impl<T> Clone for SyncView<T>
355where
356    T: Sync + [const] Clone,
357{
358    #[inline]
359    fn clone(&self) -> Self {
360        Self { inner: self.inner.clone() }
361    }
362}
363
364#[doc(hidden)]
365#[unstable(feature = "trivial_clone", issue = "none")]
366#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
367const unsafe impl<T> TrivialClone for SyncView<T> where T: Sync + [const] TrivialClone {}
368
369#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
370impl<T> Copy for SyncView<T> where T: Sync + Copy {}
371
372#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
373#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
374const impl<T, U> PartialEq<SyncView<U>> for SyncView<T>
375where
376    T: Sync + [const] PartialEq<U> + ?Sized,
377    U: Sync + ?Sized,
378{
379    #[inline]
380    fn eq(&self, other: &SyncView<U>) -> bool {
381        self.inner == other.inner
382    }
383}
384
385#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
386impl<T> StructuralPartialEq for SyncView<T> where T: Sync + StructuralPartialEq + ?Sized {}
387
388#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
389#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
390const impl<T> Eq for SyncView<T> where T: Sync + [const] Eq + ?Sized {}
391
392#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
393impl<T> Hash for SyncView<T>
394where
395    T: Sync + Hash + ?Sized,
396{
397    #[inline]
398    fn hash<H: Hasher>(&self, state: &mut H) {
399        Hash::hash(&self.inner, state)
400    }
401}
402
403#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
404#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
405const impl<T, U> PartialOrd<SyncView<U>> for SyncView<T>
406where
407    T: Sync + [const] PartialOrd<U> + ?Sized,
408    U: Sync + ?Sized,
409{
410    #[inline]
411    fn partial_cmp(&self, other: &SyncView<U>) -> Option<Ordering> {
412        self.inner.partial_cmp(&other.inner)
413    }
414}
415
416#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]
417#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
418const impl<T> Ord for SyncView<T>
419where
420    T: Sync + [const] Ord + ?Sized,
421{
422    #[inline]
423    fn cmp(&self, other: &Self) -> Ordering {
424        self.inner.cmp(&other.inner)
425    }
426}