[PATCH 1/8] rust: pin-init: internal: init: forget guards in reverse order

From: Gary Guo

Date: Tue Oct 06 2026 - 11:33:00 EST


Currently, the forget order is the same as initialization order, this is
the wrong way around compared to their drop order when going out-of-scope.
The wrong order will cause borrow checker errors if there are lifetime
dependencies between the guards. This does not matter for now because there
cannot be any lifetime dependency; it would matter for self-referential
borrows.

Reverse the order to be consistent with their out-of-scope drop order.

Signed-off-by: Gary Guo <gary@xxxxxxxxxxx>
---
rust/pin-init/internal/src/init.rs | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/rust/pin-init/internal/src/init.rs b/rust/pin-init/internal/src/init.rs
index 6605e04d49df..f0b23d0311ac 100644
--- a/rust/pin-init/internal/src/init.rs
+++ b/rust/pin-init/internal/src/init.rs
@@ -361,8 +361,7 @@ fn get_init_kind(rest: Option<(Token![..], Expr)>, dcx: &mut DiagCtxt) -> InitKi

/// Generate the code that initializes the fields of the struct using the initializers in `field`.
fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -> TokenStream {
- let mut guards = vec![];
- let mut guard_attrs = vec![];
+ let mut forget_guards = vec![];
let mut res = TokenStream::new();
for InitializerField { attrs, kind } in fields {
let cfgs = {
@@ -474,17 +473,19 @@ fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -
#binding
});

- guards.push(guard);
- guard_attrs.push(cfgs);
+ forget_guards.push(quote_spanned! { span =>
+ #(#cfgs)*
+ ::core::mem::forget(#guard);
+ });
}
+
+ forget_guards.reverse();
+
quote! {
#res
// If execution reaches this point, all fields have been initialized. Therefore we can now
// dismiss the guards by forgetting them.
- #(
- #(#guard_attrs)*
- ::core::mem::forget(#guards);
- )*
+ #(#forget_guards)*
}
}


--
2.54.0