11//! Defines [`Exclusive`].
22
3+ use core:: cmp:: Ordering ;
34use core:: fmt;
45use core:: future:: Future ;
5- use core:: marker:: Tuple ;
6+ use core:: hash:: { Hash , Hasher } ;
7+ use core:: marker:: { StructuralPartialEq , Tuple } ;
68use core:: ops:: { Coroutine , CoroutineState } ;
79use core:: pin:: Pin ;
810use core:: task:: { Context , Poll } ;
911
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.
12+ /// `Exclusive` provides _mutable_ access, also referred to as _exclusive_
13+ /// access to the underlying value. However, it only permits _immutable_, or _shared_
14+ /// access to the underlying value when that value is [`Sync`] .
1315///
1416/// 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`
17+ /// implement `Sync`. Indeed, the safety requirements of `Sync` state that for `Exclusive`
1618/// 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+ /// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive<T>` for non-`Sync` T
20+ /// has no API whatsoever, making it useless, thus harmless, thus memory safe.
1921///
2022/// Certain constructs like [`Future`]s can only be used with _exclusive_ access,
2123/// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the
2224/// Rust compiler that something is `Sync` in practice.
2325///
2426/// ## Examples
25- /// Using a non-`Sync` future prevents the wrapping struct from being `Sync`
27+ ///
28+ /// Using a non-`Sync` future prevents the wrapping struct from being `Sync`:
29+ ///
2630/// ```compile_fail
2731/// use core::cell::Cell;
2832///
@@ -43,7 +47,8 @@ use core::task::{Context, Poll};
4347/// ```
4448///
4549/// `Exclusive` ensures the struct is `Sync` without stripping the future of its
46- /// functionality.
50+ /// functionality:
51+ ///
4752/// ```
4853/// #![feature(exclusive_wrapper)]
4954/// use core::cell::Cell;
@@ -66,6 +71,7 @@ use core::task::{Context, Poll};
6671/// ```
6772///
6873/// ## Parallels with a mutex
74+ ///
6975/// In some sense, `Exclusive` can be thought of as a _compile-time_ version of
7076/// a mutex, as the borrow-checker guarantees that only one `&mut` can exist
7177/// for any value. This is a parallel with the fact that
@@ -75,7 +81,7 @@ use core::task::{Context, Poll};
7581#[ doc( alias = "SyncWrapper" ) ]
7682#[ doc( alias = "SyncCell" ) ]
7783#[ doc( alias = "Unique" ) ]
78- // `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would
84+ // `Exclusive` can't have derived `PartialOrd`, `Clone`, etc. impls as they would
7985// use `&` access to the inner value, violating the `Sync` impl's safety
8086// requirements.
8187#[ derive( Default ) ]
@@ -195,6 +201,17 @@ where
195201 }
196202}
197203
204+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
205+ impl < F , Args > Fn < Args > for Exclusive < F >
206+ where
207+ F : Sync + Fn < Args > ,
208+ Args : Tuple ,
209+ {
210+ extern "rust-call" fn call ( & self , args : Args ) -> Self :: Output {
211+ self . as_ref ( ) . call ( args)
212+ }
213+ }
214+
198215#[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
199216impl < T > Future for Exclusive < T >
200217where
@@ -221,3 +238,80 @@ where
221238 G :: resume ( self . get_pin_mut ( ) , arg)
222239 }
223240}
241+
242+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
243+ impl < T > AsRef < T > for Exclusive < T >
244+ where
245+ T : Sync + ?Sized ,
246+ {
247+ #[ inline]
248+ fn as_ref ( & self ) -> & T {
249+ & self . inner
250+ }
251+ }
252+
253+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
254+ impl < T > Clone for Exclusive < T >
255+ where
256+ T : Sync + Clone ,
257+ {
258+ #[ inline]
259+ fn clone ( & self ) -> Self {
260+ Self { inner : self . inner . clone ( ) }
261+ }
262+ }
263+
264+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
265+ impl < T > Copy for Exclusive < T > where T : Sync + Copy { }
266+
267+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
268+ impl < T , U > PartialEq < Exclusive < U > > for Exclusive < T >
269+ where
270+ T : Sync + PartialEq < U > + ?Sized ,
271+ U : Sync + ?Sized ,
272+ {
273+ #[ inline]
274+ fn eq ( & self , other : & Exclusive < U > ) -> bool {
275+ self . inner == other. inner
276+ }
277+ }
278+
279+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
280+ impl < T > StructuralPartialEq for Exclusive < T > where T : Sync + StructuralPartialEq + ?Sized { }
281+
282+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
283+ impl < T > Eq for Exclusive < T > where T : Sync + Eq + ?Sized { }
284+
285+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
286+ impl < T > Hash for Exclusive < T >
287+ where
288+ T : Sync + Hash + ?Sized ,
289+ {
290+ #[ inline]
291+ fn hash < H : Hasher > ( & self , state : & mut H ) {
292+ Hash :: hash ( & self . inner , state)
293+ }
294+ }
295+
296+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
297+ impl < T , U > PartialOrd < Exclusive < U > > for Exclusive < T >
298+ where
299+ T : Sync + PartialOrd < U > + ?Sized ,
300+ U : Sync + ?Sized ,
301+ {
302+ #[ inline]
303+ fn partial_cmp ( & self , other : & Exclusive < U > ) -> Option < Ordering > {
304+ self . inner . partial_cmp ( & other. inner )
305+ }
306+ }
307+
308+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
309+ impl < T > Ord for Exclusive < T >
310+ where
311+ T : Sync + Ord + ?Sized ,
312+ {
313+ #[ inline]
314+ fn cmp ( & self , other : & Self ) -> Ordering {
315+ self . inner . cmp ( & other. inner )
316+ }
317+ }
0 commit comments