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