mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-06-08 08:17:45 +09:00
pin-init changes for v6.16
Added: - 'Wrapper<T>' trait for creating pin-initializers for wrapper structs with a structurally pinned value such as 'UnsafeCell<T>' or 'MaybeUninit<T>'. - 'MaybeZeroable' derive macro to try to derive 'Zeroable', but not error if not all fields implement it. This is needed to derive 'Zeroable' for all bindgen-generated structs. - 'unsafe fn cast_[pin_]init()' functions to unsafely change the initialized type of an initializer. These are utilized by the 'Wrapper<T>' implementations. Changed: - Added support for visibility in 'Zeroable' derive macro. - Added support for 'union's in 'Zeroable' derive macro. Upstream dev news: - The CI has been streamlined & some bugs with it have been fixed. I also added new workflows to check if the user-space version and the one in the kernel tree have diverged. - I also started to use the issues [1] tab to keep track of any problems or unexpected/unwanted things. This should help folks report and diagnose issues w.r.t. 'pin-init' better. [1]: https://github.com/rust-for-linux/pin-init/issues -----BEGIN PGP SIGNATURE----- iIgEABYKADAWIQQjEG/HT3UeYLJybLTomd21rZaLygUCaBkpnxIcbG9zc2luQGtl cm5lbC5vcmcACgkQ6Jndta2Wi8rvGAEAlmQercahKos8nEIvsP53vckky2OI7NWi /1IjnFqIx0ABAJ4Wm08BDTU3tVOI7hNWIlZbWm0U81+Alk5fgR+Ou30F =ZfOJ -----END PGP SIGNATURE----- Merge tag 'pin-init-v6.16' of https://github.com/Rust-for-Linux/linux into rust-next Pull pin-init updates from Benno Lossin: "Added: - 'Wrapper<T>' trait for creating pin-initializers for wrapper structs with a structurally pinned value such as 'UnsafeCell<T>' or 'MaybeUninit<T>'. - 'MaybeZeroable' derive macro to try to derive 'Zeroable', but not error if not all fields implement it. This is needed to derive 'Zeroable' for all bindgen-generated structs. - 'unsafe fn cast_[pin_]init()' functions to unsafely change the initialized type of an initializer. These are utilized by the 'Wrapper<T>' implementations. Changed: - Added support for visibility in 'Zeroable' derive macro. - Added support for 'union's in 'Zeroable' derive macro. Upstream dev news: - The CI has been streamlined & some bugs with it have been fixed. I also added new workflows to check if the user-space version and the one in the kernel tree have diverged. - I also started to use the issues [1] tab to keep track of any problems or unexpected/unwanted things. This should help folks report and diagnose issues w.r.t. 'pin-init' better. [1] https://github.com/rust-for-linux/pin-init/issues" * tag 'pin-init-v6.16' of https://github.com/Rust-for-Linux/linux: rust: pin-init: improve documentation for `Zeroable` derive macros rust: pin-init: fix typos rust: pin-init: add `MaybeZeroable` derive macro rust: pin-init: allow `Zeroable` derive macro to also be applied to unions rust: pin-init: allow `pub` fields in `derive(Zeroable)` rust: pin-init: Update the structural pinning link in readme. rust: pin-init: Update Changelog and Readme rust: pin-init: Implement `Wrapper` for `UnsafePinned` behind feature flag. rust: pin-init: Add the `Wrapper` trait. rust: pin-init: add `cast_[pin_]init` functions to change the initialized type rust: pin-init: examples: use `allow` instead of `expect` rust: pin-init: examples: conditionally enable `feature(lint_reasons)` rust: pin-init: internal: skip rustfmt formatting of kernel-only module rust: pin-init: synchronize README.md
This commit is contained in:
commit
b04d170621
9 changed files with 279 additions and 10 deletions
|
@ -40,6 +40,12 @@ However, using the crate on stable compilers is possible by disabling `alloc`. I
|
||||||
will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
|
will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
|
### Nightly needed for `unsafe-pinned` feature
|
||||||
|
|
||||||
|
This feature enables the `Wrapper` implementation on the unstable `core::pin::UnsafePinned` type.
|
||||||
|
This requires the [`unsafe_pinned` unstable feature](https://github.com/rust-lang/rust/issues/125735)
|
||||||
|
and therefore a nightly compiler. Note that this feature is not enabled by default.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
To initialize a `struct` with an in-place constructor you will need two things:
|
To initialize a `struct` with an in-place constructor you will need two things:
|
||||||
|
@ -216,13 +222,15 @@ the `kernel` crate. The [`sync`] module is a good starting point.
|
||||||
|
|
||||||
[`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
|
[`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
|
||||||
[pinning]: https://doc.rust-lang.org/std/pin/index.html
|
[pinning]: https://doc.rust-lang.org/std/pin/index.html
|
||||||
[structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
|
[structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning
|
||||||
[stack]: https://docs.rs/pin-init/latest/pin_init/macro.stack_pin_init.html
|
[stack]: https://docs.rs/pin-init/latest/pin_init/macro.stack_pin_init.html
|
||||||
[`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
|
|
||||||
[`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
|
|
||||||
[`impl PinInit<Foo>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
|
[`impl PinInit<Foo>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
|
||||||
[`impl PinInit<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
|
[`impl PinInit<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
|
||||||
[`impl Init<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.Init.html
|
[`impl Init<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.Init.html
|
||||||
[Rust-for-Linux]: https://rust-for-linux.com/
|
[Rust-for-Linux]: https://rust-for-linux.com/
|
||||||
|
|
||||||
<!-- cargo-rdme end -->
|
<!-- cargo-rdme end -->
|
||||||
|
|
||||||
|
<!-- These links are not picked up by cargo-rdme, since they are behind cfgs... -->
|
||||||
|
[`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
|
||||||
|
[`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#![allow(clippy::undocumented_unsafe_blocks)]
|
#![allow(clippy::undocumented_unsafe_blocks)]
|
||||||
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
||||||
|
#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#![allow(clippy::undocumented_unsafe_blocks)]
|
#![allow(clippy::undocumented_unsafe_blocks)]
|
||||||
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
||||||
|
#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
|
||||||
#![allow(clippy::missing_safety_doc)]
|
#![allow(clippy::missing_safety_doc)]
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// inspired by <https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs>
|
// inspired by <https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs>
|
||||||
#![allow(clippy::undocumented_unsafe_blocks)]
|
#![allow(clippy::undocumented_unsafe_blocks)]
|
||||||
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
||||||
|
#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
mod pthread_mtx {
|
mod pthread_mtx {
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
|
@ -40,7 +42,7 @@ mod pthread_mtx {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[expect(dead_code)]
|
#[allow(dead_code)]
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
Alloc,
|
Alloc,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#![allow(clippy::undocumented_unsafe_blocks)]
|
#![allow(clippy::undocumented_unsafe_blocks)]
|
||||||
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
||||||
|
#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
cell::{Cell, UnsafeCell},
|
cell::{Cell, UnsafeCell},
|
||||||
|
|
|
@ -22,6 +22,7 @@ use proc_macro::TokenStream;
|
||||||
#[cfg(kernel)]
|
#[cfg(kernel)]
|
||||||
#[path = "../../../macros/quote.rs"]
|
#[path = "../../../macros/quote.rs"]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
#[cfg_attr(not(kernel), rustfmt::skip)]
|
||||||
mod quote;
|
mod quote;
|
||||||
#[cfg(not(kernel))]
|
#[cfg(not(kernel))]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -46,3 +47,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
pub fn derive_zeroable(input: TokenStream) -> TokenStream {
|
pub fn derive_zeroable(input: TokenStream) -> TokenStream {
|
||||||
zeroable::derive(input.into()).into()
|
zeroable::derive(input.into()).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(MaybeZeroable)]
|
||||||
|
pub fn maybe_derive_zeroable(input: TokenStream) -> TokenStream {
|
||||||
|
zeroable::maybe_derive(input.into()).into()
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,14 @@ use proc_macro2 as proc_macro;
|
||||||
use crate::helpers::{parse_generics, Generics};
|
use crate::helpers::{parse_generics, Generics};
|
||||||
use proc_macro::{TokenStream, TokenTree};
|
use proc_macro::{TokenStream, TokenTree};
|
||||||
|
|
||||||
pub(crate) fn derive(input: TokenStream) -> TokenStream {
|
pub(crate) fn parse_zeroable_derive_input(
|
||||||
|
input: TokenStream,
|
||||||
|
) -> (
|
||||||
|
Vec<TokenTree>,
|
||||||
|
Vec<TokenTree>,
|
||||||
|
Vec<TokenTree>,
|
||||||
|
Option<TokenTree>,
|
||||||
|
) {
|
||||||
let (
|
let (
|
||||||
Generics {
|
Generics {
|
||||||
impl_generics,
|
impl_generics,
|
||||||
|
@ -64,6 +71,11 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
|
||||||
if in_generic && !inserted {
|
if in_generic && !inserted {
|
||||||
new_impl_generics.extend(quote! { : ::pin_init::Zeroable });
|
new_impl_generics.extend(quote! { : ::pin_init::Zeroable });
|
||||||
}
|
}
|
||||||
|
(rest, new_impl_generics, ty_generics, last)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn derive(input: TokenStream) -> TokenStream {
|
||||||
|
let (rest, new_impl_generics, ty_generics, last) = parse_zeroable_derive_input(input);
|
||||||
quote! {
|
quote! {
|
||||||
::pin_init::__derive_zeroable!(
|
::pin_init::__derive_zeroable!(
|
||||||
parse_input:
|
parse_input:
|
||||||
|
@ -74,3 +86,16 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn maybe_derive(input: TokenStream) -> TokenStream {
|
||||||
|
let (rest, new_impl_generics, ty_generics, last) = parse_zeroable_derive_input(input);
|
||||||
|
quote! {
|
||||||
|
::pin_init::__maybe_derive_zeroable!(
|
||||||
|
parse_input:
|
||||||
|
@sig(#(#rest)*),
|
||||||
|
@impl_generics(#(#new_impl_generics)*),
|
||||||
|
@ty_generics(#(#ty_generics)*),
|
||||||
|
@body(#last),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,12 @@
|
||||||
//! will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
|
//! will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
|
||||||
//! mode.
|
//! mode.
|
||||||
//!
|
//!
|
||||||
|
//! ## Nightly needed for `unsafe-pinned` feature
|
||||||
|
//!
|
||||||
|
//! This feature enables the `Wrapper` implementation on the unstable `core::pin::UnsafePinned` type.
|
||||||
|
//! This requires the [`unsafe_pinned` unstable feature](https://github.com/rust-lang/rust/issues/125735)
|
||||||
|
//! and therefore a nightly compiler. Note that this feature is not enabled by default.
|
||||||
|
//!
|
||||||
//! # Overview
|
//! # Overview
|
||||||
//!
|
//!
|
||||||
//! To initialize a `struct` with an in-place constructor you will need two things:
|
//! To initialize a `struct` with an in-place constructor you will need two things:
|
||||||
|
@ -241,7 +247,7 @@
|
||||||
//! [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
|
//! [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
|
||||||
//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
|
//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
|
||||||
//! [structurally pinned fields]:
|
//! [structurally pinned fields]:
|
||||||
//! https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
|
//! https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning
|
||||||
//! [stack]: crate::stack_pin_init
|
//! [stack]: crate::stack_pin_init
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
kernel,
|
kernel,
|
||||||
|
@ -269,6 +275,10 @@
|
||||||
#![forbid(missing_docs, unsafe_op_in_unsafe_fn)]
|
#![forbid(missing_docs, unsafe_op_in_unsafe_fn)]
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
#![cfg_attr(feature = "alloc", feature(allocator_api))]
|
||||||
|
#![cfg_attr(
|
||||||
|
all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED),
|
||||||
|
feature(unsafe_pinned)
|
||||||
|
)]
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
|
@ -385,9 +395,10 @@ pub use ::pin_init_internal::pin_data;
|
||||||
/// ```
|
/// ```
|
||||||
pub use ::pin_init_internal::pinned_drop;
|
pub use ::pin_init_internal::pinned_drop;
|
||||||
|
|
||||||
/// Derives the [`Zeroable`] trait for the given struct.
|
/// Derives the [`Zeroable`] trait for the given `struct` or `union`.
|
||||||
///
|
///
|
||||||
/// This can only be used for structs where every field implements the [`Zeroable`] trait.
|
/// This can only be used for `struct`s/`union`s where every field implements the [`Zeroable`]
|
||||||
|
/// trait.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -396,13 +407,54 @@ pub use ::pin_init_internal::pinned_drop;
|
||||||
///
|
///
|
||||||
/// #[derive(Zeroable)]
|
/// #[derive(Zeroable)]
|
||||||
/// pub struct DriverData {
|
/// pub struct DriverData {
|
||||||
/// id: i64,
|
/// pub(crate) id: i64,
|
||||||
/// buf_ptr: *mut u8,
|
/// buf_ptr: *mut u8,
|
||||||
/// len: usize,
|
/// len: usize,
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use pin_init::Zeroable;
|
||||||
|
///
|
||||||
|
/// #[derive(Zeroable)]
|
||||||
|
/// pub union SignCast {
|
||||||
|
/// signed: i64,
|
||||||
|
/// unsigned: u64,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
pub use ::pin_init_internal::Zeroable;
|
pub use ::pin_init_internal::Zeroable;
|
||||||
|
|
||||||
|
/// Derives the [`Zeroable`] trait for the given `struct` or `union` if all fields implement
|
||||||
|
/// [`Zeroable`].
|
||||||
|
///
|
||||||
|
/// Contrary to the derive macro named [`macro@Zeroable`], this one silently fails when a field
|
||||||
|
/// doesn't implement [`Zeroable`].
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use pin_init::MaybeZeroable;
|
||||||
|
///
|
||||||
|
/// // implmements `Zeroable`
|
||||||
|
/// #[derive(MaybeZeroable)]
|
||||||
|
/// pub struct DriverData {
|
||||||
|
/// pub(crate) id: i64,
|
||||||
|
/// buf_ptr: *mut u8,
|
||||||
|
/// len: usize,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // does not implmement `Zeroable`
|
||||||
|
/// #[derive(MaybeZeroable)]
|
||||||
|
/// pub struct DriverData2 {
|
||||||
|
/// pub(crate) id: i64,
|
||||||
|
/// buf_ptr: *mut u8,
|
||||||
|
/// len: usize,
|
||||||
|
/// // this field doesn't implement `Zeroable`
|
||||||
|
/// other_data: &'static i32,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub use ::pin_init_internal::MaybeZeroable;
|
||||||
|
|
||||||
/// Initialize and pin a type directly on the stack.
|
/// Initialize and pin a type directly on the stack.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -1216,6 +1268,38 @@ pub const unsafe fn init_from_closure<T: ?Sized, E>(
|
||||||
__internal::InitClosure(f, PhantomData)
|
__internal::InitClosure(f, PhantomData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Changes the to be initialized type.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - `*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`.
|
||||||
|
#[expect(clippy::let_and_return)]
|
||||||
|
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.
|
||||||
|
let res = unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) };
|
||||||
|
// FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a
|
||||||
|
// cycle when computing the type returned by this function)
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Changes the to be initialized type.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - `*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`.
|
||||||
|
#[expect(clippy::let_and_return)]
|
||||||
|
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.
|
||||||
|
let res = unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) };
|
||||||
|
// FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a
|
||||||
|
// cycle when computing the type returned by this function)
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
/// An initializer that leaves the memory uninitialized.
|
/// An initializer that leaves the memory uninitialized.
|
||||||
///
|
///
|
||||||
/// The initializer is a no-op. The `slot` memory is not changed.
|
/// The initializer is a no-op. The `slot` memory is not changed.
|
||||||
|
@ -1481,3 +1565,55 @@ macro_rules! impl_tuple_zeroable {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);
|
impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);
|
||||||
|
|
||||||
|
/// This trait allows creating an instance of `Self` which contains exactly one
|
||||||
|
/// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).
|
||||||
|
///
|
||||||
|
/// This is useful when using wrapper `struct`s like [`UnsafeCell`] or with new-type `struct`s.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use core::cell::UnsafeCell;
|
||||||
|
/// # use pin_init::{pin_data, pin_init, Wrapper};
|
||||||
|
///
|
||||||
|
/// #[pin_data]
|
||||||
|
/// struct Foo {}
|
||||||
|
///
|
||||||
|
/// #[pin_data]
|
||||||
|
/// struct Bar {
|
||||||
|
/// #[pin]
|
||||||
|
/// content: UnsafeCell<Foo>
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// let foo_initializer = pin_init!(Foo{});
|
||||||
|
/// let initializer = pin_init!(Bar {
|
||||||
|
/// content <- UnsafeCell::pin_init(foo_initializer)
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
pub trait Wrapper<T> {
|
||||||
|
/// Creates an pin-initializer for a [`Self`] containing `T` from the `value_init` initializer.
|
||||||
|
fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Wrapper<T> for UnsafeCell<T> {
|
||||||
|
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> {
|
||||||
|
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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED))]
|
||||||
|
impl<T> Wrapper<T> for core::pin::UnsafePinned<T> {
|
||||||
|
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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1393,7 +1393,37 @@ macro_rules! __derive_zeroable {
|
||||||
@body({
|
@body({
|
||||||
$(
|
$(
|
||||||
$(#[$($field_attr:tt)*])*
|
$(#[$($field_attr:tt)*])*
|
||||||
$field:ident : $field_ty:ty
|
$field_vis:vis $field:ident : $field_ty:ty
|
||||||
|
),* $(,)?
|
||||||
|
}),
|
||||||
|
) => {
|
||||||
|
// SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
|
||||||
|
#[automatically_derived]
|
||||||
|
unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
|
||||||
|
where
|
||||||
|
$($($whr)*)?
|
||||||
|
{}
|
||||||
|
const _: () = {
|
||||||
|
fn assert_zeroable<T: ?::core::marker::Sized + $crate::Zeroable>() {}
|
||||||
|
fn ensure_zeroable<$($impl_generics)*>()
|
||||||
|
where $($($whr)*)?
|
||||||
|
{
|
||||||
|
$(assert_zeroable::<$field_ty>();)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
(parse_input:
|
||||||
|
@sig(
|
||||||
|
$(#[$($struct_attr:tt)*])*
|
||||||
|
$vis:vis union $name:ident
|
||||||
|
$(where $($whr:tt)*)?
|
||||||
|
),
|
||||||
|
@impl_generics($($impl_generics:tt)*),
|
||||||
|
@ty_generics($($ty_generics:tt)*),
|
||||||
|
@body({
|
||||||
|
$(
|
||||||
|
$(#[$($field_attr:tt)*])*
|
||||||
|
$field_vis:vis $field:ident : $field_ty:ty
|
||||||
),* $(,)?
|
),* $(,)?
|
||||||
}),
|
}),
|
||||||
) => {
|
) => {
|
||||||
|
@ -1413,3 +1443,62 @@ macro_rules! __derive_zeroable {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! __maybe_derive_zeroable {
|
||||||
|
(parse_input:
|
||||||
|
@sig(
|
||||||
|
$(#[$($struct_attr:tt)*])*
|
||||||
|
$vis:vis struct $name:ident
|
||||||
|
$(where $($whr:tt)*)?
|
||||||
|
),
|
||||||
|
@impl_generics($($impl_generics:tt)*),
|
||||||
|
@ty_generics($($ty_generics:tt)*),
|
||||||
|
@body({
|
||||||
|
$(
|
||||||
|
$(#[$($field_attr:tt)*])*
|
||||||
|
$field_vis:vis $field:ident : $field_ty:ty
|
||||||
|
),* $(,)?
|
||||||
|
}),
|
||||||
|
) => {
|
||||||
|
// SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
|
||||||
|
#[automatically_derived]
|
||||||
|
unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
|
||||||
|
where
|
||||||
|
$(
|
||||||
|
// the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds`
|
||||||
|
// feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>.
|
||||||
|
$field_ty: for<'__dummy> $crate::Zeroable,
|
||||||
|
)*
|
||||||
|
$($($whr)*)?
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
(parse_input:
|
||||||
|
@sig(
|
||||||
|
$(#[$($struct_attr:tt)*])*
|
||||||
|
$vis:vis union $name:ident
|
||||||
|
$(where $($whr:tt)*)?
|
||||||
|
),
|
||||||
|
@impl_generics($($impl_generics:tt)*),
|
||||||
|
@ty_generics($($ty_generics:tt)*),
|
||||||
|
@body({
|
||||||
|
$(
|
||||||
|
$(#[$($field_attr:tt)*])*
|
||||||
|
$field_vis:vis $field:ident : $field_ty:ty
|
||||||
|
),* $(,)?
|
||||||
|
}),
|
||||||
|
) => {
|
||||||
|
// SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
|
||||||
|
#[automatically_derived]
|
||||||
|
unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
|
||||||
|
where
|
||||||
|
$(
|
||||||
|
// the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds`
|
||||||
|
// feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>.
|
||||||
|
$field_ty: for<'__dummy> $crate::Zeroable,
|
||||||
|
)*
|
||||||
|
$($($whr)*)?
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue