Skip to content

Commit 578eb8b

Browse files
y86-devojeda
authored andcommitted
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 <[email protected]> Reviewed-by: Fiona Behrens <[email protected]> Reviewed-by: Andreas Hindborg <[email protected]> Tested-by: Andreas Hindborg <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent c2ddbdb commit 578eb8b

File tree

2 files changed

+126
-42
lines changed

2 files changed

+126
-42
lines changed

rust/kernel/init.rs

+113
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,116 @@
133133
//! }
134134
//! }
135135
//! ```
136+
137+
/// Construct an in-place fallible initializer for `struct`s.
138+
///
139+
/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
140+
/// [`init!`].
141+
///
142+
/// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
143+
/// append `? $type` after the `struct` initializer.
144+
/// The safety caveats from [`try_pin_init!`] also apply:
145+
/// - `unsafe` code must guarantee either full initialization or return an error and allow
146+
/// deallocation of the memory.
147+
/// - the fields are initialized in the order given in the initializer.
148+
/// - no references to fields are allowed to be created inside of the initializer.
149+
///
150+
/// # Examples
151+
///
152+
/// ```rust
153+
/// use kernel::{init::zeroed, error::Error};
154+
/// struct BigBuf {
155+
/// big: KBox<[u8; 1024 * 1024 * 1024]>,
156+
/// small: [u8; 1024 * 1024],
157+
/// }
158+
///
159+
/// impl BigBuf {
160+
/// fn new() -> impl Init<Self, Error> {
161+
/// try_init!(Self {
162+
/// big: KBox::init(zeroed(), GFP_KERNEL)?,
163+
/// small: [0; 1024 * 1024],
164+
/// }? Error)
165+
/// }
166+
/// }
167+
/// ```
168+
///
169+
/// [`Infallible`]: core::convert::Infallible
170+
/// [`init!`]: crate::init!
171+
/// [`try_pin_init!`]: crate::try_pin_init!
172+
/// [`Error`]: crate::error::Error
173+
#[macro_export]
174+
macro_rules! try_init {
175+
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
176+
$($fields:tt)*
177+
}) => {
178+
$crate::_try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
179+
$($fields)*
180+
}? $crate::error::Error)
181+
};
182+
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
183+
$($fields:tt)*
184+
}? $err:ty) => {
185+
$crate::_try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
186+
$($fields)*
187+
}? $err)
188+
};
189+
}
190+
191+
/// Construct an in-place, fallible pinned initializer for `struct`s.
192+
///
193+
/// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].
194+
///
195+
/// You can use the `?` operator or use `return Err(err)` inside the initializer to stop
196+
/// initialization and return the error.
197+
///
198+
/// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
199+
/// initialization fails, the memory can be safely deallocated without any further modifications.
200+
///
201+
/// This macro defaults the error to [`Error`].
202+
///
203+
/// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`
204+
/// after the `struct` initializer to specify the error type you want to use.
205+
///
206+
/// # Examples
207+
///
208+
/// ```rust
209+
/// # #![feature(new_uninit)]
210+
/// use kernel::{init::zeroed, error::Error};
211+
/// #[pin_data]
212+
/// struct BigBuf {
213+
/// big: KBox<[u8; 1024 * 1024 * 1024]>,
214+
/// small: [u8; 1024 * 1024],
215+
/// ptr: *mut u8,
216+
/// }
217+
///
218+
/// impl BigBuf {
219+
/// fn new() -> impl PinInit<Self, Error> {
220+
/// try_pin_init!(Self {
221+
/// big: KBox::init(zeroed(), GFP_KERNEL)?,
222+
/// small: [0; 1024 * 1024],
223+
/// ptr: core::ptr::null_mut(),
224+
/// }? Error)
225+
/// }
226+
/// }
227+
/// ```
228+
///
229+
/// [`Infallible`]: core::convert::Infallible
230+
/// [`pin_init!`]: crate::pin_init
231+
/// [`Error`]: crate::error::Error
232+
#[macro_export]
233+
macro_rules! try_pin_init {
234+
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
235+
$($fields:tt)*
236+
}) => {
237+
$crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
238+
$($fields)*
239+
}? $crate::error::Error)
240+
};
241+
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
242+
$($fields:tt)*
243+
}? $err:ty) => {
244+
$crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
245+
$($fields)*
246+
}? $err)
247+
};
248+
}

rust/pin-init/src/lib.rs

+13-42
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ macro_rules! stack_try_pin_init {
481481

482482
/// Construct an in-place, pinned initializer for `struct`s.
483483
///
484-
/// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
484+
/// This macro defaults the error to [`Infallible`]. If you need a different error, then use
485485
/// [`try_pin_init!`].
486486
///
487487
/// The syntax is almost identical to that of a normal `struct` initializer:
@@ -676,7 +676,7 @@ macro_rules! pin_init {
676676
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
677677
$($fields:tt)*
678678
}) => {
679-
$crate::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
679+
$crate::_try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
680680
$($fields)*
681681
}? ::core::convert::Infallible)
682682
};
@@ -692,9 +692,7 @@ macro_rules! pin_init {
692692
/// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
693693
/// initialization fails, the memory can be safely deallocated without any further modifications.
694694
///
695-
/// This macro defaults the error to [`Error`].
696-
///
697-
/// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`
695+
/// The syntax is identical to [`pin_init!`] with the following exception: you must append `? $type`
698696
/// after the `struct` initializer to specify the error type you want to use.
699697
///
700698
/// # Examples
@@ -724,21 +722,7 @@ macro_rules! pin_init {
724722
// For a detailed example of how this macro works, see the module documentation of the hidden
725723
// module `__internal` inside of `init/__internal.rs`.
726724
#[macro_export]
727-
macro_rules! try_pin_init {
728-
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
729-
$($fields:tt)*
730-
}) => {
731-
$crate::__init_internal!(
732-
@this($($this)?),
733-
@typ($t $(::<$($generics),*>)? ),
734-
@fields($($fields)*),
735-
@error($crate::error::Error),
736-
@data(PinData, use_data),
737-
@has_data(HasPinData, __pin_data),
738-
@construct_closure(pin_init_from_closure),
739-
@munch_fields($($fields)*),
740-
)
741-
};
725+
macro_rules! _try_pin_init {
742726
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
743727
$($fields:tt)*
744728
}? $err:ty) => {
@@ -752,12 +736,12 @@ macro_rules! try_pin_init {
752736
@construct_closure(pin_init_from_closure),
753737
@munch_fields($($fields)*),
754738
)
755-
};
739+
}
756740
}
757741

758742
/// Construct an in-place initializer for `struct`s.
759743
///
760-
/// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
744+
/// This macro defaults the error to [`Infallible`]. If you need a different error, then use
761745
/// [`try_init!`].
762746
///
763747
/// The syntax is identical to [`pin_init!`] and its safety caveats also apply:
@@ -777,19 +761,19 @@ macro_rules! init {
777761
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
778762
$($fields:tt)*
779763
}) => {
780-
$crate::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
764+
$crate::_try_init!($(&$this in)? $t $(::<$($generics),*>)? {
781765
$($fields)*
782766
}? ::core::convert::Infallible)
783767
}
784768
}
785769

786770
/// Construct an in-place fallible initializer for `struct`s.
787771
///
788-
/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
772+
/// If the initialization can complete without error (or [`Infallible`]), then use
789773
/// [`init!`].
790774
///
791-
/// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
792-
/// append `? $type` after the `struct` initializer.
775+
/// The syntax is identical to [`try_pin_init!`]. You need to specify a custom error
776+
/// via `? $type` after the `struct` initializer.
793777
/// The safety caveats from [`try_pin_init!`] also apply:
794778
/// - `unsafe` code must guarantee either full initialization or return an error and allow
795779
/// deallocation of the memory.
@@ -816,24 +800,11 @@ macro_rules! init {
816800
/// }
817801
/// }
818802
/// ```
803+
/// [`try_pin_init!`]: crate::try_pin_init
819804
// For a detailed example of how this macro works, see the module documentation of the hidden
820805
// module `__internal` inside of `init/__internal.rs`.
821806
#[macro_export]
822-
macro_rules! try_init {
823-
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
824-
$($fields:tt)*
825-
}) => {
826-
$crate::__init_internal!(
827-
@this($($this)?),
828-
@typ($t $(::<$($generics),*>)?),
829-
@fields($($fields)*),
830-
@error($crate::error::Error),
831-
@data(InitData, /*no use_data*/),
832-
@has_data(HasInitData, __init_data),
833-
@construct_closure(init_from_closure),
834-
@munch_fields($($fields)*),
835-
)
836-
};
807+
macro_rules! _try_init {
837808
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
838809
$($fields:tt)*
839810
}? $err:ty) => {
@@ -847,7 +818,7 @@ macro_rules! try_init {
847818
@construct_closure(init_from_closure),
848819
@munch_fields($($fields)*),
849820
)
850-
};
821+
}
851822
}
852823

853824
/// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is

0 commit comments

Comments
 (0)