#[repr(transparent)]pub struct SyncView<T: ?Sized> {
inner: T,
}exclusive_wrapper #98407)Expand description
SyncView 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 SyncView to unconditionally
implement Sync. Indeed, the safety requirements of Sync state that for SyncView
to be Sync, it must be sound to share across threads, that is, it must be sound
for &SyncView to cross thread boundaries. By design, a &SyncView<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 SyncView 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();
}
});SyncView ensures the struct is Sync without stripping the future of its
functionality:
#![feature(exclusive_wrapper)]
use core::cell::Cell;
use core::sync::SyncView;
async fn other() {}
fn assert_sync<T: Sync>(t: T) {}
struct State<F> {
future: SyncView<F>
}
assert_sync(State {
future: SyncView::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, SyncView 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.
Fields§
§inner: Texclusive_wrapper #98407)Implementations§
Source§impl<T: ?Sized> SyncView<T>
impl<T: ?Sized> SyncView<T>
Sourcepub const fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>
🔬This is a nightly-only experimental API. (exclusive_wrapper #98407)
pub const fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>
exclusive_wrapper #98407)Gets pinned exclusive access to the underlying value.
SyncView is considered to structurally pin the underlying
value, which means unpinned SyncViews can produce unpinned
access to the underlying value, but pinned SyncViews only
produce pinned access to the underlying value.
Sourcepub const fn from_mut(r: &mut T) -> &mut SyncView<T> ⓘ
🔬This is a nightly-only experimental API. (exclusive_wrapper #98407)
pub const fn from_mut(r: &mut T) -> &mut SyncView<T> ⓘ
exclusive_wrapper #98407)Build a mutable reference to an SyncView<T> from
a mutable reference to a T. This allows you to skip
building an SyncView with SyncView::new.
Sourcepub const fn from_pin_mut(r: Pin<&mut T>) -> Pin<&mut SyncView<T>>
🔬This is a nightly-only experimental API. (exclusive_wrapper #98407)
pub const fn from_pin_mut(r: Pin<&mut T>) -> Pin<&mut SyncView<T>>
exclusive_wrapper #98407)Build a pinned mutable reference to an SyncView<T> from
a pinned mutable reference to a T. This allows you to skip
building an SyncView with SyncView::new.
Source§impl<T: ?Sized + Sync> SyncView<T>
impl<T: ?Sized + Sync> SyncView<T>
Sourcepub const fn as_pin(self: Pin<&Self>) -> Pin<&T>
🔬This is a nightly-only experimental API. (exclusive_wrapper #98407)
pub const fn as_pin(self: Pin<&Self>) -> Pin<&T>
exclusive_wrapper #98407)Gets pinned shared access to the underlying value.
SyncView is considered to structurally pin the underlying
value, which means unpinned SyncViews can produce unpinned
access to the underlying value, but pinned SyncViews only
produce pinned access to the underlying value.
Trait Implementations§
Source§impl<F, Args> AsyncFn<Args> for SyncView<F>
impl<F, Args> AsyncFn<Args> for SyncView<F>
Source§extern "rust-call" fn async_call(
&self,
args: Args,
) -> Self::CallRefFuture<'_>
extern "rust-call" fn async_call( &self, args: Args, ) -> Self::CallRefFuture<'_>
async_fn_traits)AsyncFn, returning a future which may borrow from the called closure.Source§impl<F, Args> AsyncFnMut<Args> for SyncView<F>where
F: AsyncFnMut<Args>,
Args: Tuple,
impl<F, Args> AsyncFnMut<Args> for SyncView<F>where
F: AsyncFnMut<Args>,
Args: Tuple,
Source§type CallRefFuture<'a> = <F as AsyncFnMut<Args>>::CallRefFuture<'a>
where
F: 'a
type CallRefFuture<'a> = <F as AsyncFnMut<Args>>::CallRefFuture<'a> where F: 'a
async_fn_traits)AsyncFnMut::async_call_mut and AsyncFn::async_call.Source§extern "rust-call" fn async_call_mut(
&mut self,
args: Args,
) -> Self::CallRefFuture<'_>
extern "rust-call" fn async_call_mut( &mut self, args: Args, ) -> Self::CallRefFuture<'_>
async_fn_traits)AsyncFnMut, returning a future which may borrow from the called closure.Source§impl<F, Args> AsyncFnOnce<Args> for SyncView<F>where
F: AsyncFnOnce<Args>,
Args: Tuple,
impl<F, Args> AsyncFnOnce<Args> for SyncView<F>where
F: AsyncFnOnce<Args>,
Args: Tuple,
Source§type CallOnceFuture = <F as AsyncFnOnce<Args>>::CallOnceFuture
type CallOnceFuture = <F as AsyncFnOnce<Args>>::CallOnceFuture
async_fn_traits)AsyncFnOnce::async_call_once.Source§type Output = <F as AsyncFnOnce<Args>>::Output
type Output = <F as AsyncFnOnce<Args>>::Output
async_fn_traits)Source§extern "rust-call" fn async_call_once(
self,
args: Args,
) -> Self::CallOnceFuture
extern "rust-call" fn async_call_once( self, args: Args, ) -> Self::CallOnceFuture
async_fn_traits)AsyncFnOnce, returning a future which may move out of the called closure.Source§impl<R, G> Coroutine<R> for SyncView<G>
impl<R, G> Coroutine<R> for SyncView<G>
Source§type Yield = <G as Coroutine<R>>::Yield
type Yield = <G as Coroutine<R>>::Yield
coroutine_trait #43122)Source§impl<T> Eq for SyncView<T>
impl<T> Eq for SyncView<T>
1.0.0 · Source§#[doc(hidden)]fn assert_receiver_is_total_eq(&self)
#[doc(hidden)]fn assert_receiver_is_total_eq(&self)
implementation detail of #[derive(Eq)]
Source§#[doc(hidden)]fn assert_fields_are_eq(&self)
#[doc(hidden)]fn assert_fields_are_eq(&self)
derive_eq_internals)Source§impl<T> Ord for SyncView<T>
impl<T> Ord for SyncView<T>
Source§impl<T, U> PartialOrd<SyncView<U>> for SyncView<T>
impl<T, U> PartialOrd<SyncView<U>> for SyncView<T>
Source§#[doc(hidden)]fn __chaining_lt(&self, other: &Rhs) -> ControlFlow<bool>
#[doc(hidden)]fn __chaining_lt(&self, other: &Rhs) -> ControlFlow<bool>
partial_ord_chaining_methods)self == other, returns ControlFlow::Continue(()).
Otherwise, returns ControlFlow::Break(self < other). Read moreSource§#[doc(hidden)]fn __chaining_le(&self, other: &Rhs) -> ControlFlow<bool>
#[doc(hidden)]fn __chaining_le(&self, other: &Rhs) -> ControlFlow<bool>
partial_ord_chaining_methods)__chaining_lt, but for <= instead of <.Source§#[doc(hidden)]fn __chaining_gt(&self, other: &Rhs) -> ControlFlow<bool>
#[doc(hidden)]fn __chaining_gt(&self, other: &Rhs) -> ControlFlow<bool>
partial_ord_chaining_methods)__chaining_lt, but for > instead of <.Source§#[doc(hidden)]fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool>
#[doc(hidden)]fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool>
partial_ord_chaining_methods)__chaining_lt, but for >= instead of <.impl<T> Copy for SyncView<T>
impl<T> StructuralPartialEq for SyncView<T>
impl<T: ?Sized> Sync for SyncView<T>
impl<T> TrivialClone for SyncView<T>where
T: Sync + TrivialClone,
Auto Trait Implementations§
impl<T> Freeze for SyncView<T>
impl<T> RefUnwindSafe for SyncView<T>where
T: RefUnwindSafe + ?Sized,
impl<T> Send for SyncView<T>
impl<T> Unpin for SyncView<T>
impl<T> UnsafeUnpin for SyncView<T>where
T: UnsafeUnpin + ?Sized,
impl<T> UnwindSafe for SyncView<T>where
T: UnwindSafe + ?Sized,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<F> IntoFuture for Fwhere
F: Future,
impl<F> IntoFuture for Fwhere
F: Future,
Source§type IntoFuture = F
type IntoFuture = F
Source§fn into_future(self) -> <F as IntoFuture>::IntoFuture
fn into_future(self) -> <F as IntoFuture>::IntoFuture
Source§impl<F> Pattern for F
impl<F> Pattern for F
Source§type Searcher<'a> = CharPredicateSearcher<'a, F>
type Searcher<'a> = CharPredicateSearcher<'a, F>
pattern #27721)Source§fn into_searcher<'a>(self, haystack: &'a str) -> CharPredicateSearcher<'a, F>
fn into_searcher<'a>(self, haystack: &'a str) -> CharPredicateSearcher<'a, F>
pattern #27721)self and the haystack to search in.Source§fn is_contained_in<'a>(self, haystack: &'a str) -> bool
fn is_contained_in<'a>(self, haystack: &'a str) -> bool
pattern #27721)Source§fn is_prefix_of<'a>(self, haystack: &'a str) -> bool
fn is_prefix_of<'a>(self, haystack: &'a str) -> bool
pattern #27721)Source§fn strip_prefix_of<'a>(self, haystack: &'a str) -> Option<&'a str>
fn strip_prefix_of<'a>(self, haystack: &'a str) -> Option<&'a str>
pattern #27721)Source§fn is_suffix_of<'a>(self, haystack: &'a str) -> boolwhere
CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
fn is_suffix_of<'a>(self, haystack: &'a str) -> boolwhere
CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
pattern #27721)Source§fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str>where
CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str>where
CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
pattern #27721)Source§fn as_utf8_pattern(&self) -> Option<Utf8Pattern<'_>>
fn as_utf8_pattern(&self) -> Option<Utf8Pattern<'_>>
pattern #27721)Source§impl<T> SizedTypeProperties for T
impl<T> SizedTypeProperties for T
Source§#[doc(hidden)]const SIZE: usize = _
#[doc(hidden)]const SIZE: usize = _
sized_type_properties)Source§#[doc(hidden)]const ALIGN: usize = _
#[doc(hidden)]const ALIGN: usize = _
sized_type_properties)Source§#[doc(hidden)]const ALIGNMENT: Alignment = _
#[doc(hidden)]const ALIGNMENT: Alignment = _
ptr_alignment_type #102070)Source§#[doc(hidden)]const IS_ZST: bool = _
#[doc(hidden)]const IS_ZST: bool = _
sized_type_properties)Source§#[doc(hidden)]const LAYOUT: Layout = _
#[doc(hidden)]const LAYOUT: Layout = _
sized_type_properties)Source§#[doc(hidden)]const MAX_SLICE_LEN: usize = _
#[doc(hidden)]const MAX_SLICE_LEN: usize = _
sized_type_properties)[Self]. Read more