diff options
| author | Gary Guo <gary@garyguo.net> | 2026-05-12 13:09:49 +0100 |
|---|---|---|
| committer | Gary Guo <gary@garyguo.net> | 2026-05-18 12:18:06 +0100 |
| commit | df1827babd665ea7039383dbc5c671b66a65c1ec (patch) | |
| tree | 7f485ce6138653e3a6e172862f48a2212c8e9ca4 /rust | |
| parent | fea304ec875454360a3be106e0baad96032bf9fe (diff) | |
| download | linux-next-history-df1827babd665ea7039383dbc5c671b66a65c1ec.tar.gz | |
rust: pin-init: internal: init: handle code blocks early
`InitializerKind::Code` is a special case where it does not initialize a
field, and thus generate no guard and accessors. Handle it earlier and make
the rest of the code more linear.
Signed-off-by: Gary Guo <gary@garyguo.net>
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/pin-init/internal/src/init.rs | 100 |
1 files changed, 55 insertions, 45 deletions
diff --git a/rust/pin-init/internal/src/init.rs b/rust/pin-init/internal/src/init.rs index b0bfe44695e19..7eda1bcf0f28b 100644 --- a/rust/pin-init/internal/src/init.rs +++ b/rust/pin-init/internal/src/init.rs @@ -231,6 +231,20 @@ fn init_fields( cfgs.retain(|attr| attr.path().is_ident("cfg")); cfgs }; + + let ident = match kind { + InitializerKind::Value { ident, .. } => ident, + InitializerKind::Init { ident, .. } => ident, + InitializerKind::Code { block, .. } => { + res.extend(quote! { + #(#attrs)* + #[allow(unused_braces)] + #block + }); + continue; + } + }; + let init = match kind { InitializerKind::Value { ident, value } => { let mut value_ident = ident.clone(); @@ -283,55 +297,51 @@ fn init_fields( } } } - InitializerKind::Code { block: value, .. } => quote! { - #(#attrs)* - #[allow(unused_braces)] - #value - }, + InitializerKind::Code { .. } => unreachable!(), }; - res.extend(init); - if let Some(ident) = kind.ident() { - // `mixed_site` ensures that the guard is not accessible to the user-controlled code. - let guard = format_ident!("__{ident}_guard", span = Span::mixed_site()); - // NOTE: The reference is derived from the guard so that it only lives as long as the - // guard does and cannot escape the scope. If it's created via `&mut (*#slot).#ident` - // like the unaligned field guard, it will become effectively `'static`. - let accessor = if pinned { - let project_ident = format_ident!("__project_{ident}"); - quote! { - // SAFETY: the initialization is pinned. - unsafe { #data.#project_ident(#guard.let_binding()) } - } - } else { - quote! { - #guard.let_binding() - } - }; + // `mixed_site` ensures that the guard is not accessible to the user-controlled code. + let guard = format_ident!("__{ident}_guard", span = Span::mixed_site()); - res.extend(quote! { - #(#cfgs)* - // Create the drop guard. - // - // SAFETY: - // - `&raw mut (*slot).#ident` is valid. - // - `make_field_check` checks that `&raw mut (*slot).#ident` is properly aligned. - // - `(*slot).#ident` has been initialized above. - // - We only need the ownership to the pointee back when initialization has - // succeeded, where we `forget` the guard. - let mut #guard = unsafe { - ::pin_init::__internal::DropGuard::new( - &raw mut (*slot).#ident - ) - }; + // NOTE: The reference is derived from the guard so that it only lives as long as the + // guard does and cannot escape the scope. If it's created via `&mut (*#slot).#ident` + // like the unaligned field guard, it will become effectively `'static`. + let accessor = if pinned { + let project_ident = format_ident!("__project_{ident}"); + quote! { + // SAFETY: the initialization is pinned. + unsafe { #data.#project_ident(#guard.let_binding()) } + } + } else { + quote! { + #guard.let_binding() + } + }; - #(#cfgs)* - #[allow(unused_variables)] - let #ident = #accessor; - }); - guards.push(guard); - guard_attrs.push(cfgs); - } + res.extend(quote! { + #init + + #(#cfgs)* + // Create the drop guard. + // + // SAFETY: + // - `&raw mut (*slot).#ident` is valid. + // - `make_field_check` checks that `&raw mut (*slot).#ident` is properly aligned. + // - `(*slot).#ident` has been initialized above. + // - We only need the ownership to the pointee back when initialization has + // succeeded, where we `forget` the guard. + let mut #guard = unsafe { + ::pin_init::__internal::DropGuard::new( + &raw mut (*slot).#ident + ) + }; + + #(#cfgs)* + #[allow(unused_variables)] + let #ident = #accessor; + }); + guards.push(guard); + guard_attrs.push(cfgs); } quote! { #res |
