From: Gary Guo <gary@garyguo.net>
To: "Benno Lossin" <lossin@kernel.org>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>
Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
Gary Guo <gary@garyguo.net>
Subject: [PATCH 1/8] rust: pin-init: internal: pin_data: use closure for `handle_field`
Date: Tue, 12 May 2026 13:09:46 +0100 [thread overview]
Message-ID: <20260512-pin-init-sync-v1-1-81963130dfbd@garyguo.net> (raw)
In-Reply-To: <20260512-pin-init-sync-v1-0-81963130dfbd@garyguo.net>
`handle_field` is currently a function, which precludes it from referencing
things in the scope of the parent function. Given that it's only called
once, inline its contents to the closure that invokes it instead, so it can
directly reference `struct_name` without having to pass in as argument.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/pin-init/internal/src/pin_data.rs | 144 ++++++++++++++++-----------------
1 file changed, 70 insertions(+), 74 deletions(-)
diff --git a/rust/pin-init/internal/src/pin_data.rs b/rust/pin-init/internal/src/pin_data.rs
index be3d97a38225..1a7098a4c6e0 100644
--- a/rust/pin-init/internal/src/pin_data.rs
+++ b/rust/pin-init/internal/src/pin_data.rs
@@ -336,7 +336,7 @@ impl #impl_generics #ident #ty_generics
fn generate_the_pin_data(
vis: &Visibility,
- ident: &Ident,
+ struct_name: &Ident,
generics: &Generics,
fields: &[(bool, &Field)],
) -> TokenStream {
@@ -347,78 +347,74 @@ fn generate_the_pin_data(
// not structurally pinned, then it can be initialized via `Init`.
//
// The functions are `unsafe` to prevent accidentally calling them.
- fn handle_field(
- Field {
- vis,
- ident,
- ty,
- attrs,
- ..
- }: &Field,
- struct_ident: &Ident,
- pinned: bool,
- ) -> TokenStream {
- let ident = ident
- .as_ref()
- .expect("only structs with named fields are supported");
- let project_ident = format_ident!("__project_{ident}");
- let (init_ty, init_fn, project_ty, project_body, pin_safety) = if pinned {
- (
- quote!(PinInit),
- quote!(__pinned_init),
- quote!(::core::pin::Pin<&'__slot mut #ty>),
- // SAFETY: this field is structurally pinned.
- quote!(unsafe { ::core::pin::Pin::new_unchecked(slot) }),
- quote!(
- /// - `slot` will not move until it is dropped, i.e. it will be pinned.
- ),
- )
- } else {
- (
- quote!(Init),
- quote!(__init),
- quote!(&'__slot mut #ty),
- quote!(slot),
- quote!(),
- )
- };
- let slot_safety = format!(
- " `slot` points at the field `{ident}` inside of `{struct_ident}`, which is pinned.",
- );
- quote! {
- /// # Safety
- ///
- /// - `slot` is a valid pointer to uninitialized memory.
- /// - the caller does not touch `slot` when `Err` is returned, they are only permitted
- /// to deallocate.
- #pin_safety
- #(#attrs)*
- #vis unsafe fn #ident<E>(
- self,
- slot: *mut #ty,
- init: impl ::pin_init::#init_ty<#ty, E>,
- ) -> ::core::result::Result<(), E> {
- // SAFETY: this function has the same safety requirements as the __init function
- // called below.
- unsafe { ::pin_init::#init_ty::#init_fn(init, slot) }
- }
-
- /// # Safety
- ///
- #[doc = #slot_safety]
- #(#attrs)*
- #vis unsafe fn #project_ident<'__slot>(
- self,
- slot: &'__slot mut #ty,
- ) -> #project_ty {
- #project_body
- }
- }
- }
-
let field_accessors = fields
.iter()
- .map(|(pinned, field)| handle_field(field, ident, *pinned))
+ .map(|(pinned, field)| {
+ let Field {
+ vis,
+ ident,
+ ty,
+ attrs,
+ ..
+ } = field;
+
+ let field_name = ident
+ .as_ref()
+ .expect("only structs with named fields are supported");
+ let project_ident = format_ident!("__project_{field_name}");
+ let (init_ty, init_fn, project_ty, project_body, pin_safety) = if *pinned {
+ (
+ quote!(PinInit),
+ quote!(__pinned_init),
+ quote!(::core::pin::Pin<&'__slot mut #ty>),
+ // SAFETY: this field is structurally pinned.
+ quote!(unsafe { ::core::pin::Pin::new_unchecked(slot) }),
+ quote!(
+ /// - `slot` will not move until it is dropped, i.e. it will be pinned.
+ ),
+ )
+ } else {
+ (
+ quote!(Init),
+ quote!(__init),
+ quote!(&'__slot mut #ty),
+ quote!(slot),
+ quote!(),
+ )
+ };
+ let slot_safety = format!(
+ " `slot` points at the field `{field_name}` inside of `{struct_name}`, which is pinned.",
+ );
+ quote! {
+ /// # Safety
+ ///
+ /// - `slot` is a valid pointer to uninitialized memory.
+ /// - the caller does not touch `slot` when `Err` is returned, they are only
+ /// permitted to deallocate.
+ #pin_safety
+ #(#attrs)*
+ #vis unsafe fn #field_name<E>(
+ self,
+ slot: *mut #ty,
+ init: impl ::pin_init::#init_ty<#ty, E>,
+ ) -> ::core::result::Result<(), E> {
+ // SAFETY: this function has the same safety requirements as the __init function
+ // called below.
+ unsafe { ::pin_init::#init_ty::#init_fn(init, slot) }
+ }
+
+ /// # Safety
+ ///
+ #[doc = #slot_safety]
+ #(#attrs)*
+ #vis unsafe fn #project_ident<'__slot>(
+ self,
+ slot: &'__slot mut #ty,
+ ) -> #project_ty {
+ #project_body
+ }
+ }
+ })
.collect::<TokenStream>();
quote! {
// We declare this struct which will host all of the projection function for our type. It
@@ -428,7 +424,7 @@ fn handle_field(
#whr
{
__phantom: ::core::marker::PhantomData<
- fn(#ident #ty_generics) -> #ident #ty_generics
+ fn(#struct_name #ty_generics) -> #struct_name #ty_generics
>,
}
@@ -452,7 +448,7 @@ impl #impl_generics __ThePinData #ty_generics
// SAFETY: We have added the correct projection functions above to `__ThePinData` and
// we also use the least restrictive generics possible.
- unsafe impl #impl_generics ::pin_init::__internal::HasPinData for #ident #ty_generics
+ unsafe impl #impl_generics ::pin_init::__internal::HasPinData for #struct_name #ty_generics
#whr
{
type PinData = __ThePinData #ty_generics;
@@ -466,7 +462,7 @@ unsafe fn __pin_data() -> Self::PinData {
unsafe impl #impl_generics ::pin_init::__internal::PinData for __ThePinData #ty_generics
#whr
{
- type Datee = #ident #ty_generics;
+ type Datee = #struct_name #ty_generics;
}
}
}
--
2.51.2
next prev parent reply other threads:[~2026-05-12 12:10 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-12 12:09 [PATCH 0/8] rust: pin-init: internal refactors Gary Guo
2026-05-12 12:09 ` Gary Guo [this message]
2026-05-12 12:09 ` [PATCH 2/8] rust: pin-init: internal: pin_data: add struct to record field info Gary Guo
2026-05-12 12:09 ` [PATCH 3/8] rust: pin-init: internal: add `PhantomInvariant` and `PhantomInvariantLifetime` Gary Guo
2026-05-12 12:09 ` [PATCH 4/8] rust: pin-init: internal: init: handle code blocks early Gary Guo
2026-05-12 12:09 ` [PATCH 5/8] rust: pin-init: internal: use marker on drop guard type for pinned fields Gary Guo
2026-05-12 12:09 ` [PATCH 6/8] rust: pin-init: internal: make `make_closure` inherent methods Gary Guo
2026-05-12 12:09 ` [PATCH 7/8] rust: pin-init: internal: project slots instead of references Gary Guo
2026-05-12 12:09 ` [PATCH 8/8] rust: pin-init: internal: project using full slot Gary Guo
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=20260512-pin-init-sync-v1-1-81963130dfbd@garyguo.net \
--to=gary@garyguo.net \
--cc=a.hindborg@kernel.org \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
/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