mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	rust: pin-init: move the default error behavior of try_[pin_]init
				
					
				
			Move the ability to just write `try_pin_init!(Foo { a <- a_init })`
(note the missing `? Error` at the end) into the kernel crate.
Remove this notation from the pin-init crate, since the default when no
error is specified is the kernel-internal `Error` type. Instead add two
macros in the kernel crate that serve this default and are used instead
of the ones from `pin-init`.
This is done, because the `Error` type that is used as the default is
from the kernel crate and it thus prevents making the pin-init crate
standalone.
In order to not cause a build error due to a name overlap, the macros in
the pin-init crate are renamed, but this change is reverted in a future
commit when it is a standalone crate.
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Fiona Behrens <me@kloenk.dev>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250308110339.2997091-8-benno.lossin@proton.me
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									c2ddbdbb8a
								
							
						
					
					
						commit
						578eb8b6db
					
				
					 2 changed files with 126 additions and 42 deletions
				
			
		| 
						 | 
				
			
			@ -133,3 +133,116 @@
 | 
			
		|||
//!     }
 | 
			
		||||
//! }
 | 
			
		||||
//! ```
 | 
			
		||||
 | 
			
		||||
/// Construct an in-place fallible initializer for `struct`s.
 | 
			
		||||
///
 | 
			
		||||
/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
 | 
			
		||||
/// [`init!`].
 | 
			
		||||
///
 | 
			
		||||
/// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
 | 
			
		||||
/// append `? $type` after the `struct` initializer.
 | 
			
		||||
/// The safety caveats from [`try_pin_init!`] also apply:
 | 
			
		||||
/// - `unsafe` code must guarantee either full initialization or return an error and allow
 | 
			
		||||
///   deallocation of the memory.
 | 
			
		||||
/// - the fields are initialized in the order given in the initializer.
 | 
			
		||||
/// - no references to fields are allowed to be created inside of the initializer.
 | 
			
		||||
///
 | 
			
		||||
/// # Examples
 | 
			
		||||
///
 | 
			
		||||
/// ```rust
 | 
			
		||||
/// use kernel::{init::zeroed, error::Error};
 | 
			
		||||
/// struct BigBuf {
 | 
			
		||||
///     big: KBox<[u8; 1024 * 1024 * 1024]>,
 | 
			
		||||
///     small: [u8; 1024 * 1024],
 | 
			
		||||
/// }
 | 
			
		||||
///
 | 
			
		||||
/// impl BigBuf {
 | 
			
		||||
///     fn new() -> impl Init<Self, Error> {
 | 
			
		||||
///         try_init!(Self {
 | 
			
		||||
///             big: KBox::init(zeroed(), GFP_KERNEL)?,
 | 
			
		||||
///             small: [0; 1024 * 1024],
 | 
			
		||||
///         }? Error)
 | 
			
		||||
///     }
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
/// [`Infallible`]: core::convert::Infallible
 | 
			
		||||
/// [`init!`]: crate::init!
 | 
			
		||||
/// [`try_pin_init!`]: crate::try_pin_init!
 | 
			
		||||
/// [`Error`]: crate::error::Error
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! try_init {
 | 
			
		||||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }) => {
 | 
			
		||||
        $crate::_try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
 | 
			
		||||
            $($fields)*
 | 
			
		||||
        }? $crate::error::Error)
 | 
			
		||||
    };
 | 
			
		||||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }? $err:ty) => {
 | 
			
		||||
        $crate::_try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
 | 
			
		||||
            $($fields)*
 | 
			
		||||
        }? $err)
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Construct an in-place, fallible pinned initializer for `struct`s.
 | 
			
		||||
///
 | 
			
		||||
/// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].
 | 
			
		||||
///
 | 
			
		||||
/// You can use the `?` operator or use `return Err(err)` inside the initializer to stop
 | 
			
		||||
/// initialization and return the error.
 | 
			
		||||
///
 | 
			
		||||
/// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
 | 
			
		||||
/// initialization fails, the memory can be safely deallocated without any further modifications.
 | 
			
		||||
///
 | 
			
		||||
/// This macro defaults the error to [`Error`].
 | 
			
		||||
///
 | 
			
		||||
/// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`
 | 
			
		||||
/// after the `struct` initializer to specify the error type you want to use.
 | 
			
		||||
///
 | 
			
		||||
/// # Examples
 | 
			
		||||
///
 | 
			
		||||
/// ```rust
 | 
			
		||||
/// # #![feature(new_uninit)]
 | 
			
		||||
/// use kernel::{init::zeroed, error::Error};
 | 
			
		||||
/// #[pin_data]
 | 
			
		||||
/// struct BigBuf {
 | 
			
		||||
///     big: KBox<[u8; 1024 * 1024 * 1024]>,
 | 
			
		||||
///     small: [u8; 1024 * 1024],
 | 
			
		||||
///     ptr: *mut u8,
 | 
			
		||||
/// }
 | 
			
		||||
///
 | 
			
		||||
/// impl BigBuf {
 | 
			
		||||
///     fn new() -> impl PinInit<Self, Error> {
 | 
			
		||||
///         try_pin_init!(Self {
 | 
			
		||||
///             big: KBox::init(zeroed(), GFP_KERNEL)?,
 | 
			
		||||
///             small: [0; 1024 * 1024],
 | 
			
		||||
///             ptr: core::ptr::null_mut(),
 | 
			
		||||
///         }? Error)
 | 
			
		||||
///     }
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
/// [`Infallible`]: core::convert::Infallible
 | 
			
		||||
/// [`pin_init!`]: crate::pin_init
 | 
			
		||||
/// [`Error`]: crate::error::Error
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! try_pin_init {
 | 
			
		||||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }) => {
 | 
			
		||||
        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
 | 
			
		||||
            $($fields)*
 | 
			
		||||
        }? $crate::error::Error)
 | 
			
		||||
    };
 | 
			
		||||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }? $err:ty) => {
 | 
			
		||||
        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
 | 
			
		||||
            $($fields)*
 | 
			
		||||
        }? $err)
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -481,7 +481,7 @@ macro_rules! stack_try_pin_init {
 | 
			
		|||
 | 
			
		||||
/// Construct an in-place, pinned initializer for `struct`s.
 | 
			
		||||
///
 | 
			
		||||
/// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
 | 
			
		||||
/// This macro defaults the error to [`Infallible`]. If you need a different error, then use
 | 
			
		||||
/// [`try_pin_init!`].
 | 
			
		||||
///
 | 
			
		||||
/// The syntax is almost identical to that of a normal `struct` initializer:
 | 
			
		||||
| 
						 | 
				
			
			@ -676,7 +676,7 @@ macro_rules! pin_init {
 | 
			
		|||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }) => {
 | 
			
		||||
        $crate::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
 | 
			
		||||
        $crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
 | 
			
		||||
            $($fields)*
 | 
			
		||||
        }? ::core::convert::Infallible)
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -692,9 +692,7 @@ macro_rules! pin_init {
 | 
			
		|||
/// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
 | 
			
		||||
/// initialization fails, the memory can be safely deallocated without any further modifications.
 | 
			
		||||
///
 | 
			
		||||
/// This macro defaults the error to [`Error`].
 | 
			
		||||
///
 | 
			
		||||
/// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`
 | 
			
		||||
/// The syntax is identical to [`pin_init!`] with the following exception: you must append `? $type`
 | 
			
		||||
/// after the `struct` initializer to specify the error type you want to use.
 | 
			
		||||
///
 | 
			
		||||
/// # Examples
 | 
			
		||||
| 
						 | 
				
			
			@ -724,21 +722,7 @@ macro_rules! pin_init {
 | 
			
		|||
// For a detailed example of how this macro works, see the module documentation of the hidden
 | 
			
		||||
// module `__internal` inside of `init/__internal.rs`.
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! try_pin_init {
 | 
			
		||||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }) => {
 | 
			
		||||
        $crate::__init_internal!(
 | 
			
		||||
            @this($($this)?),
 | 
			
		||||
            @typ($t $(::<$($generics),*>)? ),
 | 
			
		||||
            @fields($($fields)*),
 | 
			
		||||
            @error($crate::error::Error),
 | 
			
		||||
            @data(PinData, use_data),
 | 
			
		||||
            @has_data(HasPinData, __pin_data),
 | 
			
		||||
            @construct_closure(pin_init_from_closure),
 | 
			
		||||
            @munch_fields($($fields)*),
 | 
			
		||||
        )
 | 
			
		||||
    };
 | 
			
		||||
macro_rules! _try_pin_init {
 | 
			
		||||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }? $err:ty) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -752,12 +736,12 @@ macro_rules! try_pin_init {
 | 
			
		|||
            @construct_closure(pin_init_from_closure),
 | 
			
		||||
            @munch_fields($($fields)*),
 | 
			
		||||
        )
 | 
			
		||||
    };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Construct an in-place initializer for `struct`s.
 | 
			
		||||
///
 | 
			
		||||
/// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
 | 
			
		||||
/// This macro defaults the error to [`Infallible`]. If you need a different error, then use
 | 
			
		||||
/// [`try_init!`].
 | 
			
		||||
///
 | 
			
		||||
/// The syntax is identical to [`pin_init!`] and its safety caveats also apply:
 | 
			
		||||
| 
						 | 
				
			
			@ -777,7 +761,7 @@ macro_rules! init {
 | 
			
		|||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }) => {
 | 
			
		||||
        $crate::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
 | 
			
		||||
        $crate::_try_init!($(&$this in)? $t $(::<$($generics),*>)? {
 | 
			
		||||
            $($fields)*
 | 
			
		||||
        }? ::core::convert::Infallible)
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -785,11 +769,11 @@ macro_rules! init {
 | 
			
		|||
 | 
			
		||||
/// Construct an in-place fallible initializer for `struct`s.
 | 
			
		||||
///
 | 
			
		||||
/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
 | 
			
		||||
/// If the initialization can complete without error (or [`Infallible`]), then use
 | 
			
		||||
/// [`init!`].
 | 
			
		||||
///
 | 
			
		||||
/// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
 | 
			
		||||
/// append `? $type` after the `struct` initializer.
 | 
			
		||||
/// The syntax is identical to [`try_pin_init!`]. You need to specify a custom error
 | 
			
		||||
/// via `? $type` after the `struct` initializer.
 | 
			
		||||
/// The safety caveats from [`try_pin_init!`] also apply:
 | 
			
		||||
/// - `unsafe` code must guarantee either full initialization or return an error and allow
 | 
			
		||||
///   deallocation of the memory.
 | 
			
		||||
| 
						 | 
				
			
			@ -816,24 +800,11 @@ macro_rules! init {
 | 
			
		|||
///     }
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
/// [`try_pin_init!`]: crate::try_pin_init
 | 
			
		||||
// For a detailed example of how this macro works, see the module documentation of the hidden
 | 
			
		||||
// module `__internal` inside of `init/__internal.rs`.
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! try_init {
 | 
			
		||||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }) => {
 | 
			
		||||
        $crate::__init_internal!(
 | 
			
		||||
            @this($($this)?),
 | 
			
		||||
            @typ($t $(::<$($generics),*>)?),
 | 
			
		||||
            @fields($($fields)*),
 | 
			
		||||
            @error($crate::error::Error),
 | 
			
		||||
            @data(InitData, /*no use_data*/),
 | 
			
		||||
            @has_data(HasInitData, __init_data),
 | 
			
		||||
            @construct_closure(init_from_closure),
 | 
			
		||||
            @munch_fields($($fields)*),
 | 
			
		||||
        )
 | 
			
		||||
    };
 | 
			
		||||
macro_rules! _try_init {
 | 
			
		||||
    ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
 | 
			
		||||
        $($fields:tt)*
 | 
			
		||||
    }? $err:ty) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -847,7 +818,7 @@ macro_rules! try_init {
 | 
			
		|||
            @construct_closure(init_from_closure),
 | 
			
		||||
            @munch_fields($($fields)*),
 | 
			
		||||
        )
 | 
			
		||||
    };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue