From: Benno Lossin <benno.lossin@proton.me>
To: Miguel Ojeda <ojeda@kernel.org>,
Wedson Almeida Filho <wedsonaf@gmail.com>,
Alex Gaynor <alex.gaynor@gmail.com>
Cc: "Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Alice Ryhl" <aliceryhl@google.com>,
"Andreas Hindborg" <nmi@metaspace.dk>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 12/12] rust: init: update expanded macro explanation
Date: Wed, 19 Jul 2023 14:21:26 +0000 [thread overview]
Message-ID: <20230719141918.543938-13-benno.lossin@proton.me> (raw)
In-Reply-To: <20230719141918.543938-1-benno.lossin@proton.me>
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.
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
---
rust/kernel/init/macros.rs | 126 ++++++++++++++++++++-----------------
1 file changed, 69 insertions(+), 57 deletions(-)
diff --git a/rust/kernel/init/macros.rs b/rust/kernel/init/macros.rs
index 345cfc0e6d37..1d492c4bab69 100644
--- a/rust/kernel/init/macros.rs
+++ b/rust/kernel/init/macros.rs
@@ -45,7 +45,7 @@
//! #[pinned_drop]
//! impl PinnedDrop for Foo {
//! 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,
//! }
//! #[doc(hidden)]
-//! impl<'__pin, T>
-//! ::core::marker::Unpin for Bar<T> where __Unpin<'__pin, T>: ::core::marker::Unpin {}
+//! impl<'__pin, T> ::core::marker::Unpin for Bar<T>
+//! where
+//! __Unpin<'__pin, T>: ::core::marker::Unpin,
+//! {}
//! // 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
//! // 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`.
//! #[allow(non_camel_case_types)]
//! trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
-//! impl<T: ::kernel::init::PinnedDrop>
-//! UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
+//! impl<
+//! T: ::kernel::init::PinnedDrop,
+//! > UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for 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
//! // there will be no possibility of returning without `unsafe`.
//! 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
//! // - we `use` the `HasPinData` trait in the block, it is only available in that
//! // scope.
@@ -227,8 +230,7 @@
//! use ::kernel::init::__internal::HasPinData;
//! Self::__pin_data()
//! };
-//! // Use `data` to help with type inference, the closure supplied will have the type
-//! // `FnOnce(*mut Self) -> Result<__InitOk, Infallible>`.
+//! // Ensure that `data` really is of type `PinData` and help with type inference:
//! let init = ::kernel::init::__internal::PinData::make_closure::<
//! _,
//! __InitOk,
@@ -236,71 +238,75 @@
//! >(data, move |slot| {
//! {
//! // 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
-//! // that will refer to this struct instead of the one defined above.
+//! // tries to write `return Ok(__InitOk)`, then they get a type error,
+//! // since that will refer to this struct instead of the one defined
+//! // above.
//! struct __InitOk;
//! // This is the expansion of `t,`, which is syntactic sugar for `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
-//! // error later. This `DropGuard` will drop the field when it gets dropped
-//! // and has not yet been forgotten. We make a reference to it, so users
-//! // cannot `mem::forget` it from the initializer, since the name is the same
-//! // as the field (including hygiene).
-//! let t = &unsafe {
-//! ::kernel::init::__internal::DropGuard::new(
-//! ::core::addr_of_mut!((*slot).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 error later. This `DropGuard` will drop the field when it gets
+//! // dropped and has not yet been forgotten.
+//! let t = unsafe {
+//! ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
//! };
//! // Expansion of `x: 0,`:
-//! // Since this can be an arbitrary expression we cannot place it inside of
-//! // the `unsafe` block, so we bind it here.
-//! let x = 0;
-//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
+//! // Since this can be an arbitrary expression we cannot place it inside
+//! // of the `unsafe` block, so we bind it here.
+//! {
+//! let x = 0;
+//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
+//! }
//! // We again create a `DropGuard`.
-//! let x = &unsafe {
-//! ::kernel::init::__internal::DropGuard::new(
-//! ::core::addr_of_mut!((*slot).x),
-//! )
+//! let x = unsafe {
+//! ::kernel::init::__internal::DropGuard::new(::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
//! // initialized exactly once, since this is `if false` it will never get
//! // executed, but still type-checked.
-//! // Additionally we abuse `slot` to automatically infer the correct type for
-//! // the struct. This is also another check that every field is accessible
-//! // from this scope.
+//! // Additionally we abuse `slot` to automatically infer the correct type
+//! // for the struct. This is also another check that every field is
+//! // accessible from this scope.
//! #[allow(unreachable_code, clippy::diverging_sub_expression)]
-//! if false {
+//! let _ = || {
//! unsafe {
//! ::core::ptr::write(
//! slot,
//! Self {
-//! // We only care about typecheck finding every field here,
-//! // the expression does not matter, just conjure one using
-//! // `panic!()`:
+//! // We only care about typecheck finding every field
+//! // here, the expression does not matter, just conjure
+//! // one using `panic!()`:
//! t: ::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
//! // `__InitOk` that we need to return.
//! Ok(__InitOk)
//! });
//! // 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| ())
//! };
//! // Construct the initializer.
//! let init = unsafe {
-//! ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
+//! ::kernel::init::pin_init_from_closure::<
+//! _,
+//! ::core::convert::Infallible,
+//! >(init)
//! };
//! init
//! }
@@ -374,7 +380,10 @@
//! b: Bar<u32>,
//! }
//! #[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
//! // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like
//! // before, instead we implement `Drop` here and delegate to `PinnedDrop`.
@@ -403,7 +412,7 @@
//! #[pinned_drop]
//! impl PinnedDrop for Foo {
//! 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 impl ::kernel::init::PinnedDrop for Foo {
//! 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| {
//! {
//! struct __InitOk;
-//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
-//! let a = &unsafe {
+//! {
+//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
+//! }
+//! let a = unsafe {
//! ::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)? };
-//! let b = &unsafe {
+//! let b = unsafe {
//! ::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)]
-//! if false {
+//! let _ = || {
//! unsafe {
//! ::core::ptr::write(
//! slot,
@@ -470,13 +482,13 @@
//! },
//! );
//! };
-//! }
-//! unsafe { ::kernel::init::__internal::DropGuard::forget(a) };
-//! unsafe { ::kernel::init::__internal::DropGuard::forget(b) };
+//! };
//! }
//! 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| ())
//! };
//! let init = unsafe {
--
2.41.0
next prev parent reply other threads:[~2023-07-19 14:22 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-19 14:20 [PATCH v2 00/12] Quality of life improvements for pin-init Benno Lossin
2023-07-19 14:20 ` [PATCH v2 01/12] rust: init: consolidate init macros Benno Lossin
2023-07-19 18:37 ` Martin Rodriguez Reboredo
2023-07-20 13:09 ` Alice Ryhl
2023-07-19 14:20 ` [PATCH v2 02/12] rust: add derive macro for `Zeroable` Benno Lossin
2023-07-19 18:42 ` Martin Rodriguez Reboredo
2023-07-20 13:13 ` Alice Ryhl
2023-07-19 14:20 ` [PATCH v2 03/12] rust: init: make guards in the init macros hygienic Benno Lossin
2023-07-19 19:04 ` Martin Rodriguez Reboredo
2023-07-20 13:16 ` Alice Ryhl
2023-07-19 14:20 ` [PATCH v2 04/12] rust: init: wrap type checking struct initializers in a closure Benno Lossin
2023-07-19 19:05 ` Martin Rodriguez Reboredo
2023-07-20 13:17 ` Alice Ryhl
2023-07-19 14:20 ` [PATCH v2 05/12] rust: init: make initializer values inaccessible after initializing Benno Lossin
2023-07-19 19:07 ` Martin Rodriguez Reboredo
2023-07-20 13:19 ` Alice Ryhl
2023-07-19 14:20 ` [PATCH v2 06/12] rust: init: add `..Zeroable::zeroed()` syntax for zeroing all missing fields Benno Lossin
2023-07-20 13:25 ` Alice Ryhl
2023-07-20 13:51 ` Martin Rodriguez Reboredo
2023-07-19 14:20 ` [PATCH v2 07/12] rust: init: Add functions to create array initializers Benno Lossin
2023-07-20 13:28 ` Alice Ryhl
2023-07-20 13:59 ` Martin Rodriguez Reboredo
2023-07-19 14:21 ` [PATCH v2 08/12] rust: init: add support for arbitrary paths in init macros Benno Lossin
2023-07-20 13:30 ` Alice Ryhl
2023-07-20 14:02 ` Martin Rodriguez Reboredo
2023-07-19 14:21 ` [PATCH v2 09/12] rust: init: implement Zeroable for Opaque<T> Benno Lossin
2023-07-20 13:34 ` Alice Ryhl
2023-07-24 14:16 ` Benno Lossin
2023-07-25 11:57 ` Alice Ryhl
2023-07-29 4:11 ` Benno Lossin
2023-07-29 8:14 ` Alice Ryhl
2023-07-20 14:03 ` Martin Rodriguez Reboredo
2023-07-19 14:21 ` [PATCH v2 10/12] rust: init: make `PinInit<T, E>` a supertrait of `Init<T, E>` Benno Lossin
2023-07-20 13:36 ` Alice Ryhl
2023-07-20 14:07 ` Martin Rodriguez Reboredo
2023-07-19 14:21 ` [PATCH v2 11/12] rust: init: add `{pin_}chain` functions to `{Pin}Init<T, E>` Benno Lossin
2023-07-21 0:23 ` Martin Rodriguez Reboredo
2023-07-24 14:08 ` Benno Lossin
2023-07-24 16:07 ` Martin Rodriguez Reboredo
2023-07-24 21:55 ` Benno Lossin
2023-07-19 14:21 ` Benno Lossin [this message]
2023-07-21 0:24 ` [PATCH v2 12/12] rust: init: update expanded macro explanation Martin Rodriguez Reboredo
2023-07-19 15:23 ` [PATCH v2 00/12] Quality of life improvements for pin-init Benno Lossin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230719141918.543938-13-benno.lossin@proton.me \
--to=benno.lossin@proton.me \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=nmi@metaspace.dk \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=wedsonaf@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).