mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
rust: init: update expanded macro explanation
The previous patches changed the internals of the macros resulting in the example expanded code being outdated. This patch updates the example and only changes documentation. Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com> Signed-off-by: Benno Lossin <benno.lossin@proton.me> Link: https://lore.kernel.org/r/20230814084602.25699-14-benno.lossin@proton.me Reviewed-by: Alice Ryhl <aliceryhl@google.com> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
parent
7f8977a7fe
commit
4af84c6a85
1 changed files with 69 additions and 57 deletions
|
@ -45,7 +45,7 @@
|
||||||
//! #[pinned_drop]
|
//! #[pinned_drop]
|
||||||
//! impl PinnedDrop for Foo {
|
//! impl PinnedDrop for Foo {
|
||||||
//! fn drop(self: Pin<&mut Self>) {
|
//! fn drop(self: Pin<&mut Self>) {
|
||||||
//! println!("{self:p} is getting dropped.");
|
//! pr_info!("{self:p} is getting dropped.");
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
@ -170,8 +170,10 @@
|
||||||
//! t: T,
|
//! t: T,
|
||||||
//! }
|
//! }
|
||||||
//! #[doc(hidden)]
|
//! #[doc(hidden)]
|
||||||
//! impl<'__pin, T>
|
//! impl<'__pin, T> ::core::marker::Unpin for Bar<T>
|
||||||
//! ::core::marker::Unpin for Bar<T> where __Unpin<'__pin, T>: ::core::marker::Unpin {}
|
//! where
|
||||||
|
//! __Unpin<'__pin, T>: ::core::marker::Unpin,
|
||||||
|
//! {}
|
||||||
//! // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users
|
//! // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users
|
||||||
//! // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to
|
//! // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to
|
||||||
//! // UB with only safe code, so we disallow this by giving a trait implementation error using
|
//! // UB with only safe code, so we disallow this by giving a trait implementation error using
|
||||||
|
@ -188,8 +190,9 @@
|
||||||
//! // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`.
|
//! // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`.
|
||||||
//! #[allow(non_camel_case_types)]
|
//! #[allow(non_camel_case_types)]
|
||||||
//! trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
|
//! trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
|
||||||
//! impl<T: ::kernel::init::PinnedDrop>
|
//! impl<
|
||||||
//! UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
|
//! T: ::kernel::init::PinnedDrop,
|
||||||
|
//! > UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
|
||||||
//! impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {}
|
//! impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {}
|
||||||
//! };
|
//! };
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -219,7 +222,7 @@
|
||||||
//! // return type and shadow it later when we insert the arbitrary user code. That way
|
//! // return type and shadow it later when we insert the arbitrary user code. That way
|
||||||
//! // there will be no possibility of returning without `unsafe`.
|
//! // there will be no possibility of returning without `unsafe`.
|
||||||
//! struct __InitOk;
|
//! struct __InitOk;
|
||||||
//! // Get the pin-data type from the initialized type.
|
//! // Get the data about fields from the supplied type.
|
||||||
//! // - the function is unsafe, hence the unsafe block
|
//! // - the function is unsafe, hence the unsafe block
|
||||||
//! // - we `use` the `HasPinData` trait in the block, it is only available in that
|
//! // - we `use` the `HasPinData` trait in the block, it is only available in that
|
||||||
//! // scope.
|
//! // scope.
|
||||||
|
@ -227,8 +230,7 @@
|
||||||
//! use ::kernel::init::__internal::HasPinData;
|
//! use ::kernel::init::__internal::HasPinData;
|
||||||
//! Self::__pin_data()
|
//! Self::__pin_data()
|
||||||
//! };
|
//! };
|
||||||
//! // Use `data` to help with type inference, the closure supplied will have the type
|
//! // Ensure that `data` really is of type `PinData` and help with type inference:
|
||||||
//! // `FnOnce(*mut Self) -> Result<__InitOk, Infallible>`.
|
|
||||||
//! let init = ::kernel::init::__internal::PinData::make_closure::<
|
//! let init = ::kernel::init::__internal::PinData::make_closure::<
|
||||||
//! _,
|
//! _,
|
||||||
//! __InitOk,
|
//! __InitOk,
|
||||||
|
@ -236,71 +238,75 @@
|
||||||
//! >(data, move |slot| {
|
//! >(data, move |slot| {
|
||||||
//! {
|
//! {
|
||||||
//! // Shadow the structure so it cannot be used to return early. If a user
|
//! // Shadow the structure so it cannot be used to return early. If a user
|
||||||
//! // tries to write `return Ok(__InitOk)`, then they get a type error, since
|
//! // tries to write `return Ok(__InitOk)`, then they get a type error,
|
||||||
//! // that will refer to this struct instead of the one defined above.
|
//! // since that will refer to this struct instead of the one defined
|
||||||
|
//! // above.
|
||||||
//! struct __InitOk;
|
//! struct __InitOk;
|
||||||
//! // This is the expansion of `t,`, which is syntactic sugar for `t: t,`.
|
//! // This is the expansion of `t,`, which is syntactic sugar for `t: t,`.
|
||||||
|
//! {
|
||||||
//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) };
|
//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) };
|
||||||
//! // Since initialization could fail later (not in this case, since the error
|
//! }
|
||||||
//! // type is `Infallible`) we will need to drop this field if there is an
|
//! // Since initialization could fail later (not in this case, since the
|
||||||
//! // error later. This `DropGuard` will drop the field when it gets dropped
|
//! // error type is `Infallible`) we will need to drop this field if there
|
||||||
//! // and has not yet been forgotten. We make a reference to it, so users
|
//! // is an error later. This `DropGuard` will drop the field when it gets
|
||||||
//! // cannot `mem::forget` it from the initializer, since the name is the same
|
//! // dropped and has not yet been forgotten.
|
||||||
//! // as the field (including hygiene).
|
//! let t = unsafe {
|
||||||
//! let t = &unsafe {
|
//! ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
|
||||||
//! ::kernel::init::__internal::DropGuard::new(
|
|
||||||
//! ::core::addr_of_mut!((*slot).t),
|
|
||||||
//! )
|
|
||||||
//! };
|
//! };
|
||||||
//! // Expansion of `x: 0,`:
|
//! // Expansion of `x: 0,`:
|
||||||
//! // Since this can be an arbitrary expression we cannot place it inside of
|
//! // Since this can be an arbitrary expression we cannot place it inside
|
||||||
//! // the `unsafe` block, so we bind it here.
|
//! // of the `unsafe` block, so we bind it here.
|
||||||
|
//! {
|
||||||
//! let x = 0;
|
//! let x = 0;
|
||||||
//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
|
//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
|
||||||
|
//! }
|
||||||
//! // We again create a `DropGuard`.
|
//! // We again create a `DropGuard`.
|
||||||
//! let x = &unsafe {
|
//! let x = unsafe {
|
||||||
//! ::kernel::init::__internal::DropGuard::new(
|
//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x))
|
||||||
//! ::core::addr_of_mut!((*slot).x),
|
|
||||||
//! )
|
|
||||||
//! };
|
//! };
|
||||||
//!
|
//! // Since initialization has successfully completed, we can now forget
|
||||||
|
//! // the guards. This is not `mem::forget`, since we only have
|
||||||
|
//! // `&DropGuard`.
|
||||||
|
//! ::core::mem::forget(x);
|
||||||
|
//! ::core::mem::forget(t);
|
||||||
//! // Here we use the type checker to ensure that every field has been
|
//! // Here we use the type checker to ensure that every field has been
|
||||||
//! // initialized exactly once, since this is `if false` it will never get
|
//! // initialized exactly once, since this is `if false` it will never get
|
||||||
//! // executed, but still type-checked.
|
//! // executed, but still type-checked.
|
||||||
//! // Additionally we abuse `slot` to automatically infer the correct type for
|
//! // Additionally we abuse `slot` to automatically infer the correct type
|
||||||
//! // the struct. This is also another check that every field is accessible
|
//! // for the struct. This is also another check that every field is
|
||||||
//! // from this scope.
|
//! // accessible from this scope.
|
||||||
//! #[allow(unreachable_code, clippy::diverging_sub_expression)]
|
//! #[allow(unreachable_code, clippy::diverging_sub_expression)]
|
||||||
//! if false {
|
//! let _ = || {
|
||||||
//! unsafe {
|
//! unsafe {
|
||||||
//! ::core::ptr::write(
|
//! ::core::ptr::write(
|
||||||
//! slot,
|
//! slot,
|
||||||
//! Self {
|
//! Self {
|
||||||
//! // We only care about typecheck finding every field here,
|
//! // We only care about typecheck finding every field
|
||||||
//! // the expression does not matter, just conjure one using
|
//! // here, the expression does not matter, just conjure
|
||||||
//! // `panic!()`:
|
//! // one using `panic!()`:
|
||||||
//! t: ::core::panic!(),
|
//! t: ::core::panic!(),
|
||||||
//! x: ::core::panic!(),
|
//! x: ::core::panic!(),
|
||||||
//! },
|
//! },
|
||||||
//! );
|
//! );
|
||||||
//! };
|
//! };
|
||||||
//! }
|
//! };
|
||||||
//! // Since initialization has successfully completed, we can now forget the
|
|
||||||
//! // guards. This is not `mem::forget`, since we only have `&DropGuard`.
|
|
||||||
//! unsafe { ::kernel::init::__internal::DropGuard::forget(t) };
|
|
||||||
//! unsafe { ::kernel::init::__internal::DropGuard::forget(x) };
|
|
||||||
//! }
|
//! }
|
||||||
//! // We leave the scope above and gain access to the previously shadowed
|
//! // We leave the scope above and gain access to the previously shadowed
|
||||||
//! // `__InitOk` that we need to return.
|
//! // `__InitOk` that we need to return.
|
||||||
//! Ok(__InitOk)
|
//! Ok(__InitOk)
|
||||||
//! });
|
//! });
|
||||||
//! // Change the return type from `__InitOk` to `()`.
|
//! // Change the return type from `__InitOk` to `()`.
|
||||||
//! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> {
|
//! let init = move |
|
||||||
|
//! slot,
|
||||||
|
//! | -> ::core::result::Result<(), ::core::convert::Infallible> {
|
||||||
//! init(slot).map(|__InitOk| ())
|
//! init(slot).map(|__InitOk| ())
|
||||||
//! };
|
//! };
|
||||||
//! // Construct the initializer.
|
//! // Construct the initializer.
|
||||||
//! let init = unsafe {
|
//! let init = unsafe {
|
||||||
//! ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
|
//! ::kernel::init::pin_init_from_closure::<
|
||||||
|
//! _,
|
||||||
|
//! ::core::convert::Infallible,
|
||||||
|
//! >(init)
|
||||||
//! };
|
//! };
|
||||||
//! init
|
//! init
|
||||||
//! }
|
//! }
|
||||||
|
@ -374,7 +380,10 @@
|
||||||
//! b: Bar<u32>,
|
//! b: Bar<u32>,
|
||||||
//! }
|
//! }
|
||||||
//! #[doc(hidden)]
|
//! #[doc(hidden)]
|
||||||
//! impl<'__pin> ::core::marker::Unpin for Foo where __Unpin<'__pin>: ::core::marker::Unpin {}
|
//! impl<'__pin> ::core::marker::Unpin for Foo
|
||||||
|
//! where
|
||||||
|
//! __Unpin<'__pin>: ::core::marker::Unpin,
|
||||||
|
//! {}
|
||||||
//! // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to
|
//! // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to
|
||||||
//! // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like
|
//! // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like
|
||||||
//! // before, instead we implement `Drop` here and delegate to `PinnedDrop`.
|
//! // before, instead we implement `Drop` here and delegate to `PinnedDrop`.
|
||||||
|
@ -403,7 +412,7 @@
|
||||||
//! #[pinned_drop]
|
//! #[pinned_drop]
|
||||||
//! impl PinnedDrop for Foo {
|
//! impl PinnedDrop for Foo {
|
||||||
//! fn drop(self: Pin<&mut Self>) {
|
//! fn drop(self: Pin<&mut Self>) {
|
||||||
//! println!("{self:p} is getting dropped.");
|
//! pr_info!("{self:p} is getting dropped.");
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -414,7 +423,7 @@
|
||||||
//! // `unsafe`, full path and the token parameter are added, everything else stays the same.
|
//! // `unsafe`, full path and the token parameter are added, everything else stays the same.
|
||||||
//! unsafe impl ::kernel::init::PinnedDrop for Foo {
|
//! unsafe impl ::kernel::init::PinnedDrop for Foo {
|
||||||
//! fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) {
|
//! fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) {
|
||||||
//! println!("{self:p} is getting dropped.");
|
//! pr_info!("{self:p} is getting dropped.");
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -449,18 +458,21 @@
|
||||||
//! >(data, move |slot| {
|
//! >(data, move |slot| {
|
||||||
//! {
|
//! {
|
||||||
//! struct __InitOk;
|
//! struct __InitOk;
|
||||||
|
//! {
|
||||||
//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
|
//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
|
||||||
//! let a = &unsafe {
|
//! }
|
||||||
|
//! let a = unsafe {
|
||||||
//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
|
//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
|
||||||
//! };
|
//! };
|
||||||
//! let b = Bar::new(36);
|
//! let init = Bar::new(36);
|
||||||
//! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? };
|
//! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? };
|
||||||
//! let b = &unsafe {
|
//! let b = unsafe {
|
||||||
//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
|
//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
|
||||||
//! };
|
//! };
|
||||||
//!
|
//! ::core::mem::forget(b);
|
||||||
|
//! ::core::mem::forget(a);
|
||||||
//! #[allow(unreachable_code, clippy::diverging_sub_expression)]
|
//! #[allow(unreachable_code, clippy::diverging_sub_expression)]
|
||||||
//! if false {
|
//! let _ = || {
|
||||||
//! unsafe {
|
//! unsafe {
|
||||||
//! ::core::ptr::write(
|
//! ::core::ptr::write(
|
||||||
//! slot,
|
//! slot,
|
||||||
|
@ -470,13 +482,13 @@
|
||||||
//! },
|
//! },
|
||||||
//! );
|
//! );
|
||||||
//! };
|
//! };
|
||||||
//! }
|
//! };
|
||||||
//! unsafe { ::kernel::init::__internal::DropGuard::forget(a) };
|
|
||||||
//! unsafe { ::kernel::init::__internal::DropGuard::forget(b) };
|
|
||||||
//! }
|
//! }
|
||||||
//! Ok(__InitOk)
|
//! Ok(__InitOk)
|
||||||
//! });
|
//! });
|
||||||
//! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> {
|
//! let init = move |
|
||||||
|
//! slot,
|
||||||
|
//! | -> ::core::result::Result<(), ::core::convert::Infallible> {
|
||||||
//! init(slot).map(|__InitOk| ())
|
//! init(slot).map(|__InitOk| ())
|
||||||
//! };
|
//! };
|
||||||
//! let init = unsafe {
|
//! let init = unsafe {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue