mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
rust: pin-init: internal: add PhantomInvariant and PhantomInvariantLifetime
Currently, the `pin_init` library has an `Invariant` type alias, and it is instantiated using `PhantomData`. Generated code from `pin_data` on the other hand cannot access the crate-local type alias, so it generates `PhantomData<fn(T) -> T>` directly. This is all very inconsistent, despite the exact same use case of ensuring invariance. Add `PhantomInvariant` and `PhantomInvariantLifetime` and switch all users that need to express the concept of invariance to use these. They're polyfills of unstable types in the same names in the Rust standard library. Link: https://patch.msgid.link/20260512-pin-init-sync-v1-3-81963130dfbd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
This commit is contained in:
parent
4b60f38cd2
commit
fea304ec87
|
|
@ -180,10 +180,8 @@ struct __Unpin #generics_with_pin_lt
|
|||
#where_token
|
||||
#predicates
|
||||
{
|
||||
__phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
|
||||
__phantom: ::core::marker::PhantomData<
|
||||
fn(#ident #ty_generics) -> #ident #ty_generics
|
||||
>,
|
||||
__phantom_pin: ::pin_init::__internal::PhantomInvariantLifetime<'__pin>,
|
||||
__phantom: ::pin_init::__internal::PhantomInvariant<#ident #ty_generics>,
|
||||
#(#pinned_fields),*
|
||||
}
|
||||
|
||||
|
|
@ -434,9 +432,7 @@ fn generate_the_pin_data(
|
|||
#vis struct __ThePinData #generics
|
||||
#whr
|
||||
{
|
||||
__phantom: ::core::marker::PhantomData<
|
||||
fn(#struct_name #ty_generics) -> #struct_name #ty_generics
|
||||
>,
|
||||
__phantom: ::pin_init::__internal::PhantomInvariant<#struct_name #ty_generics>,
|
||||
}
|
||||
|
||||
impl #impl_generics ::core::clone::Clone for __ThePinData #ty_generics
|
||||
|
|
@ -465,7 +461,7 @@ unsafe impl #impl_generics ::pin_init::__internal::HasPinData for #struct_name #
|
|||
type PinData = __ThePinData #ty_generics;
|
||||
|
||||
unsafe fn __pin_data() -> Self::PinData {
|
||||
__ThePinData { __phantom: ::core::marker::PhantomData }
|
||||
__ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,20 +7,62 @@
|
|||
|
||||
use super::*;
|
||||
|
||||
/// Zero-sized type used to mark a type as invariant.
|
||||
///
|
||||
/// This is a polyfill for the [unstable type] in the standard library of the same name.
|
||||
///
|
||||
/// See the [nomicon] for what subtyping is. See also [this table].
|
||||
///
|
||||
/// The reason for not using `PhantomData<*mut T>` is that that type never implements [`Send`] and
|
||||
/// [`Sync`]. Hence `fn(*mut T) -> *mut T` is used, as that type always implements them.
|
||||
///
|
||||
/// [unstable type]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomInvariant.html
|
||||
/// [nomicon]: https://doc.rust-lang.org/nomicon/subtyping.html
|
||||
/// [this table]: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns
|
||||
pub(crate) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>;
|
||||
#[repr(transparent)]
|
||||
pub struct PhantomInvariant<T: ?Sized>(PhantomData<fn(T) -> T>);
|
||||
|
||||
impl<T: ?Sized> Clone for PhantomInvariant<T> {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Copy for PhantomInvariant<T> {}
|
||||
|
||||
impl<T: ?Sized> Default for PhantomInvariant<T> {
|
||||
#[inline(always)]
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> PhantomInvariant<T> {
|
||||
#[inline(always)]
|
||||
pub const fn new() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
/// Zero-sized type used to mark a lifetime as invariant.
|
||||
///
|
||||
/// This is a polyfill for the [unstable type] in the standard library of the same name.
|
||||
///
|
||||
/// [unstable type]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomInvariantLifetime.html
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>);
|
||||
|
||||
impl PhantomInvariantLifetime<'_> {
|
||||
#[inline(always)]
|
||||
pub const fn new() -> Self {
|
||||
Self(PhantomInvariant::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)>);
|
||||
pub(crate) struct InitClosure<F, T: ?Sized, E>(pub(crate) F, pub(crate) PhantomInvariant<(E, T)>);
|
||||
|
||||
// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
|
||||
// `__init` invariants.
|
||||
|
|
@ -126,7 +168,7 @@ fn make_closure<F, E>(self, f: F) -> F
|
|||
}
|
||||
}
|
||||
|
||||
pub struct AllData<T: ?Sized>(Invariant<T>);
|
||||
pub struct AllData<T: ?Sized>(PhantomInvariant<T>);
|
||||
|
||||
impl<T: ?Sized> Clone for AllData<T> {
|
||||
fn clone(&self) -> Self {
|
||||
|
|
@ -146,7 +188,7 @@ unsafe impl<T: ?Sized> HasInitData for T {
|
|||
type InitData = AllData<T>;
|
||||
|
||||
unsafe fn __init_data() -> Self::InitData {
|
||||
AllData(PhantomData)
|
||||
AllData(PhantomInvariant::new())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -947,12 +947,12 @@ fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
|
|||
where
|
||||
F: FnOnce(Pin<&mut T>) -> Result<(), E>,
|
||||
{
|
||||
ChainPinInit(self, f, PhantomData)
|
||||
ChainPinInit(self, f, __internal::PhantomInvariant::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// An initializer returned by [`PinInit::pin_chain`].
|
||||
pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>);
|
||||
pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::PhantomInvariant<(E, T)>);
|
||||
|
||||
// SAFETY: The `__pinned_init` function is implemented such that it
|
||||
// - returns `Ok(())` on successful initialization,
|
||||
|
|
@ -1055,12 +1055,12 @@ fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
|
|||
where
|
||||
F: FnOnce(&mut T) -> Result<(), E>,
|
||||
{
|
||||
ChainInit(self, f, PhantomData)
|
||||
ChainInit(self, f, __internal::PhantomInvariant::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// An initializer returned by [`Init::chain`].
|
||||
pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>);
|
||||
pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::PhantomInvariant<(E, T)>);
|
||||
|
||||
// SAFETY: The `__init` function is implemented such that it
|
||||
// - returns `Ok(())` on successful initialization,
|
||||
|
|
@ -1108,7 +1108,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
|
|||
pub const unsafe fn pin_init_from_closure<T: ?Sized, E>(
|
||||
f: impl FnOnce(*mut T) -> Result<(), E>,
|
||||
) -> impl PinInit<T, E> {
|
||||
__internal::InitClosure(f, PhantomData)
|
||||
__internal::InitClosure(f, __internal::PhantomInvariant::new())
|
||||
}
|
||||
|
||||
/// Creates a new [`Init<T, E>`] from the given closure.
|
||||
|
|
@ -1127,7 +1127,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
|
|||
pub const unsafe fn init_from_closure<T: ?Sized, E>(
|
||||
f: impl FnOnce(*mut T) -> Result<(), E>,
|
||||
) -> impl Init<T, E> {
|
||||
__internal::InitClosure(f, PhantomData)
|
||||
__internal::InitClosure(f, __internal::PhantomInvariant::new())
|
||||
}
|
||||
|
||||
/// Changes the to be initialized type.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user