Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions internal/src/pin_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ fn generate_the_pin_data(
impl #impl_generics ::core::clone::Clone for __ThePinData #ty_generics
#whr
{
#[inline]
fn clone(&self) -> Self { *self }
}

Expand Down Expand Up @@ -499,6 +500,7 @@ fn generate_the_pin_data(
{
type PinData = __ThePinData #ty_generics;

#[inline]
unsafe fn __pin_data() -> Self::PinData {
__ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new() }
}
Expand Down
5 changes: 5 additions & 0 deletions src/__internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub unsafe trait HasInitData {
pub struct AllData<T: ?Sized>(PhantomInvariant<T>);

impl<T: ?Sized> Clone for AllData<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
Expand All @@ -127,6 +128,7 @@ impl<T: ?Sized> AllData<T> {
unsafe impl<T: ?Sized> HasInitData for T {
type InitData = AllData<T>;

#[inline]
unsafe fn __init_data() -> Self::InitData {
AllData(PhantomInvariant::new())
}
Expand Down Expand Up @@ -385,19 +387,22 @@ pub struct AlwaysFail<T: ?Sized> {

impl<T: ?Sized> AlwaysFail<T> {
/// Creates a new initializer that always fails.
#[inline]
pub fn new() -> Self {
Self { _t: PhantomData }
}
}

impl<T: ?Sized> Default for AlwaysFail<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}

// SAFETY: `__init` always fails, which is always okay.
unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> {
#[inline]
unsafe fn __init(self, _slot: *mut T) -> Result<(), ()> {
Err(())
}
Expand Down
4 changes: 4 additions & 0 deletions src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub trait InPlaceInit<T>: Sized {
/// type.
///
/// If `T: !Unpin` it will not be able to move afterwards.
#[inline]
fn pin_init(init: impl PinInit<T>) -> Result<Pin<Self>, AllocError> {
// SAFETY: We delegate to `init` and only change the error type.
let init = unsafe {
Expand All @@ -52,6 +53,7 @@ pub trait InPlaceInit<T>: Sized {
E: From<AllocError>;

/// Use the given initializer to in-place initialize a `T`.
#[inline]
fn init(init: impl Init<T>) -> Result<Self, AllocError> {
// SAFETY: We delegate to `init` and only change the error type.
let init = unsafe {
Expand Down Expand Up @@ -136,6 +138,7 @@ impl<T> InPlaceInit<T> for Arc<T> {
impl<T> InPlaceWrite<T> for Box<MaybeUninit<T>> {
type Initialized = Box<T>;

#[inline]
fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
let slot = self.as_mut_ptr();
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
Expand All @@ -145,6 +148,7 @@ impl<T> InPlaceWrite<T> for Box<MaybeUninit<T>> {
Ok(unsafe { self.assume_init() })
}

#[inline]
fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
let slot = self.as_mut_ptr();
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
Expand Down
17 changes: 17 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,7 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
/// Ok(())
/// });
/// ```
#[inline]
fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
where
F: FnOnce(Pin<&mut T>) -> Result<(), E>,
Expand Down Expand Up @@ -1003,6 +1004,7 @@ where
I: PinInit<T, E>,
F: FnOnce(Pin<&mut T>) -> Result<(), E>,
{
#[inline]
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
// SAFETY: All requirements fulfilled since this function is `__init`.
let slot = unsafe { __internal::Slot::<__internal::Pinned, _>::new(slot) };
Expand Down Expand Up @@ -1068,6 +1070,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
/// Ok(())
/// });
/// ```
#[inline]
fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
where
F: FnOnce(&mut T) -> Result<(), E>,
Expand Down Expand Up @@ -1095,6 +1098,7 @@ where
I: Init<T, E>,
F: FnOnce(&mut T) -> Result<(), E>,
{
#[inline]
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
// SAFETY: All requirements fulfilled since this function is `__init`.
let slot = unsafe { __internal::Slot::<__internal::Unpinned, _>::new(slot) };
Expand Down Expand Up @@ -1175,6 +1179,7 @@ pub const unsafe fn init_from_closure<T: ?Sized, E>(
///
/// - `*mut U` must be castable to `*mut T` and any value of type `T` written through such a
/// pointer must result in a valid `U`.
#[inline]
pub const unsafe fn cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl PinInit<U, E> {
// SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
// requirements.
Expand All @@ -1187,6 +1192,7 @@ pub const unsafe fn cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl Pin
///
/// - `*mut U` must be castable to `*mut T` and any value of type `T` written through such a
/// pointer must result in a valid `U`.
#[inline]
pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> {
// SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
// requirements.
Expand Down Expand Up @@ -1283,6 +1289,7 @@ where
/// let array: Box<[usize; 1_000]> = Box::init(init_array_from_fn(|i| i)).unwrap();
/// assert_eq!(array.len(), 1_000);
/// ```
#[inline]
pub fn init_array_from_fn<I, const N: usize, T, E>(
make_init: impl FnMut(usize) -> I,
) -> impl Init<[T; N], E>
Expand All @@ -1307,6 +1314,7 @@ where
/// Arc::pin_init(pin_init_array_from_fn(|i| CMutex::new(i))).unwrap();
/// assert_eq!(array.len(), 1_000);
/// ```
#[inline]
pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
make_init: impl FnMut(usize) -> I,
) -> impl PinInit<[T; N], E>
Expand Down Expand Up @@ -1342,6 +1350,7 @@ where
/// This initializer will first execute `lookup_bar()`, match on it, if it returned an error, the
/// initializer itself will fail with that error. If it returned `Ok`, then it will run the
/// initializer returned by the [`pin_init!`] invocation.
#[inline]
pub fn pin_init_scope<T, E, F, I>(make_init: F) -> impl PinInit<T, E>
where
F: FnOnce() -> Result<I, E>,
Expand Down Expand Up @@ -1385,6 +1394,7 @@ where
/// This initializer will first execute `lookup_bar()`, match on it, if it returned an error, the
/// initializer itself will fail with that error. If it returned `Ok`, then it will run the
/// initializer returned by the [`init!`] invocation.
#[inline]
pub fn init_scope<T, E, F, I>(make_init: F) -> impl Init<T, E>
where
F: FnOnce() -> Result<I, E>,
Expand All @@ -1409,6 +1419,7 @@ unsafe impl<T> Init<T> for T {}
// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of
// `slot`. Additionally, all pinning invariants of `T` are upheld.
unsafe impl<T> PinInit<T> for T {
#[inline]
unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> {
// SAFETY: `slot` is valid for writes by the safety requirements of this function.
unsafe { slot.write(self) };
Expand All @@ -1423,6 +1434,7 @@ unsafe impl<T, E> Init<T, E> for Result<T, E> {}
// - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld.
// - `Err(err)`, slot was not written to.
unsafe impl<T, E> PinInit<T, E> for Result<T, E> {
#[inline]
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
// SAFETY: `slot` is valid for writes by the safety requirements of this function.
unsafe { slot.write(self?) };
Expand All @@ -1449,6 +1461,7 @@ pub trait InPlaceWrite<T> {
impl<T> InPlaceWrite<T> for &'static mut MaybeUninit<T> {
type Initialized = &'static mut T;

#[inline]
fn write_init<E>(self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
let slot = self.as_mut_ptr();

Expand All @@ -1459,6 +1472,7 @@ impl<T> InPlaceWrite<T> for &'static mut MaybeUninit<T> {
unsafe { Ok(self.assume_init_mut()) }
}

#[inline]
fn write_pin_init<E>(self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
let slot = self.as_mut_ptr();

Expand Down Expand Up @@ -1764,13 +1778,15 @@ pub trait Wrapper<T> {
}

impl<T> Wrapper<T> for UnsafeCell<T> {
#[inline]
fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E> {
// SAFETY: `UnsafeCell<T>` has a compatible layout to `T`.
unsafe { cast_pin_init(value_init) }
}
}

impl<T> Wrapper<T> for MaybeUninit<T> {
#[inline]
fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E> {
// SAFETY: `MaybeUninit<T>` has a compatible layout to `T`.
unsafe { cast_pin_init(value_init) }
Expand All @@ -1779,6 +1795,7 @@ impl<T> Wrapper<T> for MaybeUninit<T> {

#[cfg(all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED))]
impl<T> Wrapper<T> for core::pin::UnsafePinned<T> {
#[inline]
fn pin_init<E>(init: impl PinInit<T, E>) -> impl PinInit<Self, E> {
// SAFETY: `UnsafePinned<T>` has a compatible layout to `T`.
unsafe { cast_pin_init(init) }
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/expand/many_generics.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const _: () = {
where
T: Bar<'a, 1>,
{
#[inline]
fn clone(&self) -> Self {
*self
}
Expand Down Expand Up @@ -153,6 +154,7 @@ const _: () = {
T: Bar<'a, 1>,
{
type PinData = __ThePinData<'a, 'b, T, SIZE>;
#[inline]
unsafe fn __pin_data() -> Self::PinData {
__ThePinData {
__phantom: ::pin_init::__internal::PhantomInvariant::new(),
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/expand/pin-data.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const _: () = {
__phantom: ::pin_init::__internal::PhantomInvariant<Foo>,
}
impl ::core::clone::Clone for __ThePinData {
#[inline]
fn clone(&self) -> Self {
*self
}
Expand Down Expand Up @@ -92,6 +93,7 @@ const _: () = {
}
unsafe impl ::pin_init::__internal::HasPinData for Foo {
type PinData = __ThePinData;
#[inline]
unsafe fn __pin_data() -> Self::PinData {
__ThePinData {
__phantom: ::pin_init::__internal::PhantomInvariant::new(),
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/expand/pinned_drop.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const _: () = {
__phantom: ::pin_init::__internal::PhantomInvariant<Foo>,
}
impl ::core::clone::Clone for __ThePinData {
#[inline]
fn clone(&self) -> Self {
*self
}
Expand Down Expand Up @@ -92,6 +93,7 @@ const _: () = {
}
unsafe impl ::pin_init::__internal::HasPinData for Foo {
type PinData = __ThePinData;
#[inline]
unsafe fn __pin_data() -> Self::PinData {
__ThePinData {
__phantom: ::pin_init::__internal::PhantomInvariant::new(),
Expand Down