//! This module contains library internal items. //! //! These items must not be used outside of this crate and the pin-init-internal crate located at //! `../internal`.
/// Module-internal type implementing `PinInit` and `Init`. /// /// It is unsafe to create this type, since the closure needs to fulfill the same safety /// requirement as the `__pinned_init`/`__init` functions. pub(crate) struct InitClosure<F, T: ?Sized, E>(pub(crate) F, pub(crate) Invariant<(E, T)>);
// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the // `__init` invariants. unsafeimpl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E> where
F: FnOnce(*mut T) -> Result<(), E>,
{ #[inline] unsafefn __init(self, slot: *mut T) -> Result<(), E> {
(self.0)(slot)
}
}
// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the // `__pinned_init` invariants. unsafeimpl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T, E> where
F: FnOnce(*mut T) -> Result<(), E>,
{ #[inline] unsafefn __pinned_init(self, slot: *mut T) -> Result<(), E> {
(self.0)(slot)
}
}
/// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate /// the pin projections within the initializers. /// /// # Safety /// /// Only the `init` module is allowed to use this trait. pubunsafetrait HasPinData { type PinData: PinData;
/// Marker trait for pinning data of structs. /// /// # Safety /// /// Only the `init` module is allowed to use this trait. pubunsafetrait PinData: Copy { type Datee: ?Sized + HasPinData;
/// Type inference helper function. fn make_closure<F, O, E>(self, f: F) -> F where
F: FnOnce(*mutSelf::Datee) -> Result<O, E>,
{
f
}
}
/// This trait is automatically implemented for every type. It aims to provide the same type /// inference help as `HasPinData`. /// /// # Safety /// /// Only the `init` module is allowed to use this trait. pubunsafetrait HasInitData { type InitData: InitData;
/// Same function as `PinData`, but for arbitrary data. /// /// # Safety /// /// Only the `init` module is allowed to use this trait. pubunsafetrait InitData: Copy { type Datee: ?Sized + HasInitData;
/// Type inference helper function. fn make_closure<F, O, E>(self, f: F) -> F where
F: FnOnce(*mutSelf::Datee) -> Result<O, E>,
{
f
}
}
/// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive. /// /// # Invariants /// /// If `self.is_init` is true, then `self.value` is initialized. /// /// [`stack_pin_init`]: crate::stack_pin_init pubstruct StackInit<T> {
value: MaybeUninit<T>,
is_init: bool,
}
impl<T> Drop for StackInit<T> { #[inline] fn drop(&mutself) { ifself.is_init { // SAFETY: As we are being dropped, we only call this once. And since `self.is_init` is // true, `self.value` is initialized. unsafe { self.value.assume_init_drop() };
}
}
}
impl<T> StackInit<T> { /// Creates a new [`StackInit<T>`] that is uninitialized. Use [`stack_pin_init`] instead of this /// primitive. /// /// [`stack_pin_init`]: crate::stack_pin_init #[inline] pubfn uninit() -> Self { Self {
value: MaybeUninit::uninit(),
is_init: false,
}
}
/// Initializes the contents and returns the result. #[inline] pubfn init<E>(self: Pin<&mutSelf>, init: impl PinInit<T, E>) -> Result<Pin<&<span style='color:red'>mut T>, E> { // SAFETY: We never move out of `this`. let this = unsafe { Pin::into_inner_unchecked(self) }; // The value is currently initialized, so it needs to be dropped before we can reuse // the memory (this is a safety guarantee of `Pin`). if this.is_init {
this.is_init = false; // SAFETY: `this.is_init` was true and therefore `this.value` is initialized. unsafe { this.value.assume_init_drop() };
} // SAFETY: The memory slot is valid and this type ensures that it will stay pinned. unsafe { init.__pinned_init(this.value.as_mut_ptr())? }; // INVARIANT: `this.value` is initialized above.
this.is_init = true; // SAFETY: The slot is now pinned, since we will never give access to `&mut T`.
Ok(unsafe { Pin::new_unchecked(this.value.assume_init_mut()) })
}
}
#[test] #[cfg(feature = "std")] fn stack_init_reuse() { use ::std::{borrow::ToOwned, println, string::String}; use core::pin::pin;
#[derive(Debug)] struct Foo {
a: usize,
b: String,
} letmut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit()); let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
slot.as_mut().init(crate::init!(Foo {
a: 42,
b: "Hello".to_owned(),
})); let value = value.unwrap();
println!("{value:?}"); let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
slot.as_mut().init(crate::init!(Foo {
a: 24,
b: "world!".to_owned(),
})); let value = value.unwrap();
println!("{value:?}");
}
/// When a value of this type is dropped, it drops a `T`. /// /// Can be forgotten to prevent the drop. pubstruct DropGuard<T: ?Sized> {
ptr: *mut T,
}
impl<T: ?Sized> DropGuard<T> { /// Creates a new [`DropGuard<T>`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped. /// /// # Safety /// /// `ptr` must be a valid pointer. /// /// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`: /// - has not been dropped, /// - is not accessible by any other means, /// - will not be dropped by any other means. #[inline] pubunsafefn new(ptr: *mut T) -> Self { Self { ptr }
}
}
impl<T: ?Sized> Drop for DropGuard<T> { #[inline] fn drop(&mutself) { // SAFETY: A `DropGuard` can only be constructed using the unsafe `new` function // ensuring that this operation is safe. unsafe { ptr::drop_in_place(self.ptr) }
}
}
/// Token used by `PinnedDrop` to prevent calling the function without creating this unsafely /// created struct. This is needed, because the `drop` function is safe, but should not be called /// manually. pubstruct OnlyCallFromDrop(());
impl OnlyCallFromDrop { /// # Safety /// /// This function should only be called from the [`Drop::drop`] function and only be used to /// delegate the destruction to the pinned destructor [`PinnedDrop::drop`] of the same type. pubunsafefn new() -> Self { Self(())
}
}
/// Initializer that always fails. /// /// Used by [`assert_pinned!`]. /// /// [`assert_pinned!`]: crate::assert_pinned pubstruct AlwaysFail<T: ?Sized> {
_t: PhantomData<T>,
}
impl<T: ?Sized> AlwaysFail<T> { /// Creates a new initializer that always fails. pubfn new() -> Self { Self { _t: PhantomData }
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.