Struct Exclusive

struct Exclusive<T: ?Sized> { ... }

Exclusive provides mutable access, also referred to as exclusive access to the underlying value. However, it only permits immutable, or shared access to the underlying value when that value is Sync.

While this may seem not very useful, it allows Exclusive to unconditionally implement Sync. Indeed, the safety requirements of Sync state that for Exclusive to be Sync, it must be sound to share across threads, that is, it must be sound for &Exclusive to cross thread boundaries. By design, a &Exclusive<T> for non-Sync T has no API whatsoever, making it useless, thus harmless, thus memory safe.

Certain constructs like Futures can only be used with exclusive access, and are often Send but not Sync, so Exclusive can be used as hint to the Rust compiler that something is Sync in practice.

Examples

Using a non-Sync future prevents the wrapping struct from being Sync:

use core::cell::Cell;

async fn other() {}
fn assert_sync<T: Sync>(t: T) {}
struct State<F> {
    future: F
}

assert_sync(State {
    future: async {
        let cell = Cell::new(1);
        let cell_ref = &cell;
        other().await;
        let value = cell_ref.get();
    }
});

Exclusive ensures the struct is Sync without stripping the future of its functionality:

#![feature(exclusive_wrapper)]
use core::cell::Cell;
use core::sync::Exclusive;

async fn other() {}
fn assert_sync<T: Sync>(t: T) {}
struct State<F> {
    future: Exclusive<F>
}

assert_sync(State {
    future: Exclusive::new(async {
        let cell = Cell::new(1);
        let cell_ref = &cell;
        other().await;
        let value = cell_ref.get();
    })
});

Parallels with a mutex

In some sense, Exclusive can be thought of as a compile-time version of a mutex, as the borrow-checker guarantees that only one &mut can exist for any value. This is a parallel with the fact that & and &mut references together can be thought of as a compile-time version of a read-write lock.

Implementations

impl<T: ?Sized> Exclusive<T>

const fn get_mut(self: &mut Self) -> &mut T

Gets exclusive access to the underlying value.

const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>

Gets pinned exclusive access to the underlying value.

Exclusive is considered to structurally pin the underlying value, which means unpinned Exclusives can produce unpinned access to the underlying value, but pinned Exclusives only produce pinned access to the underlying value.

const fn from_mut(r: &mut T) -> &mut Exclusive<T>

Build a mutable reference to an Exclusive<T> from a mutable reference to a T. This allows you to skip building an Exclusive with Exclusive::new.

const fn from_pin_mut(r: Pin<&mut T>) -> Pin<&mut Exclusive<T>>

Build a pinned mutable reference to an Exclusive<T> from a pinned mutable reference to a T. This allows you to skip building an Exclusive with Exclusive::new.

impl<T: Sized> Exclusive<T>

const fn new(t: T) -> Self

Wrap a value in an Exclusive

const fn into_inner(self: Self) -> T

Unwrap the value contained in the Exclusive

impl<F> IntoFuture for Exclusive<T>

fn into_future(self: Self) -> <F as IntoFuture>::IntoFuture

impl<F> Pattern for Exclusive<T>

fn into_searcher<'a>(self: Self, haystack: &'a str) -> CharPredicateSearcher<'a, F>
fn is_contained_in<'a>(self: Self, haystack: &'a str) -> bool
fn is_prefix_of<'a>(self: Self, haystack: &'a str) -> bool
fn strip_prefix_of<'a>(self: Self, haystack: &'a str) -> Option<&'a str>
fn is_suffix_of<'a>(self: Self, haystack: &'a str) -> bool
where
    CharPredicateSearcher<'a, F>: ReverseSearcher<'a>
fn strip_suffix_of<'a>(self: Self, haystack: &'a str) -> Option<&'a str>
where
    CharPredicateSearcher<'a, F>: ReverseSearcher<'a>

impl<F, Args> Fn for Exclusive<F>

extern Other("\"rust-call\"") fn call(self: &Self, args: Args) -> <Self as >::Output

impl<F, Args> FnMut for Exclusive<F>

extern Other("\"rust-call\"") fn call_mut(self: &mut Self, args: Args) -> <Self as >::Output

impl<F, Args> FnOnce for Exclusive<F>

extern Other("\"rust-call\"") fn call_once(self: Self, args: Args) -> <Self as >::Output

impl<R, G> Coroutine for Exclusive<G>

fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<<Self as >::Yield, <Self as >::Return>

impl<T> Any for Exclusive<T>

fn type_id(self: &Self) -> TypeId

impl<T> AsRef for Exclusive<T>

fn as_ref(self: &Self) -> &T

impl<T> Borrow for Exclusive<T>

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for Exclusive<T>

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> Clone for Exclusive<T>

fn clone(self: &Self) -> Self

impl<T> CloneToUninit for Exclusive<T>

unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)

impl<T> Copy for Exclusive<T>

impl<T> Eq for Exclusive<T>

impl<T> Freeze for Exclusive<T>

impl<T> From for Exclusive<T>

fn from(t: T) -> Self

impl<T> From for Exclusive<T>

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> From for Exclusive<T>

fn from(t: never) -> T

impl<T> Future for Exclusive<T>

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<<Self as >::Output>

impl<T> Hash for Exclusive<T>

fn hash<H: Hasher>(self: &Self, state: &mut H)

impl<T> Ord for Exclusive<T>

fn cmp(self: &Self, other: &Self) -> Ordering

impl<T> RefUnwindSafe for Exclusive<T>

impl<T> Send for Exclusive<T>

impl<T> StructuralPartialEq for Exclusive<T>

impl<T> Unpin for Exclusive<T>

impl<T> UnsafeUnpin for Exclusive<T>

impl<T> UnwindSafe for Exclusive<T>

impl<T, U> Into for Exclusive<T>

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> PartialEq for Exclusive<T>

fn eq(self: &Self, other: &Exclusive<U>) -> bool

impl<T, U> PartialOrd for Exclusive<T>

fn partial_cmp(self: &Self, other: &Exclusive<U>) -> Option<Ordering>

impl<T, U> TryFrom for Exclusive<T>

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for Exclusive<T>

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>

impl<T: $crate::default::Default + ?Sized> Default for Exclusive<T>

fn default() -> Exclusive<T>

impl<T: ?Sized> Debug for Exclusive<T>

fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result<(), Error>

impl<T: ?Sized> Sync for Exclusive<T>