From 29213c00ccaa55e8ba01cfc79a93e000b0fcacc4 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 22 Sep 2026 22:58:11 +0100 Subject: [PATCH] rust: pin-init: internal: pin_data: teach drop check about generics that cannot dangle Lifetimes not needed by drop glue are considered by Rust's drop check to be considered `#[may_dangle]`. In case for a self-referential struct, we may have fields which need lifetime of borrowed fields in their drop glue, so compiler's automatic check is insufficient. Code like this: #[pin_data] struct SelfRef<'a> { borrow: PrintOnDrop<&'owner str>, owner: &'a str, } may access `owner` during the drop, however Rust will determine that since `'a` only is used in `owner`, the `'a` lifetime may dangle during drop. This is undesirable for pin-init self references, because `&'a str` could be coerced to `&'owner str` and this could further coerce if there're implied outlives, e.g. `&'earlier_field &'owner ()` would allow `&'owner str` to further coerce to `&'earlier_field`. Thus, if any self-referential field require field lifetime access in `Drop` impl, we would need to ensure that the all generic parameters visible by self-referential fields would strictly outlive the struct. And this can be done by a simple `Drop` impl that does nothing. Without a dropck eye patch, presence of `Drop` impl, albeit empty, tells the drop check that the strict outlive relation is needed. Acked-by: Benno Lossin Link: https://patch.msgid.link/20261008-dev-selfref-v2-5-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo --- rust/pin-init/src/__internal.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs index 74dc23506d97..32bd6d8c39a1 100644 --- a/rust/pin-init/src/__internal.rs +++ b/rust/pin-init/src/__internal.rs @@ -473,6 +473,35 @@ unsafe impl Sync for Erase #[repr(transparent)] pub struct Borrowed(PhantomPinned, T); +// Lifetimes not needed by drop glue are considered by Rust's drop check to be considered +// `#[may_dangle]`. In case for a self-referential struct, we may have fields which need lifetime of +// borrowed fields in their drop glue, so compiler's automatic check is insufficient. +// +// Code like this: +// ``` +// #[pin_data] +// struct SelfRef<'a> { +// borrow: PrintOnDrop<&'owner str>, +// owner: &'a str, +// } +// ``` +// may access `owner` during the drop, however Rust will determine that since `'a` only is used in +// `owner`, the `'a` lifetime may dangle during drop. +// +// This is undesirable for pin-init self references, because `&'a str` could be coerecd to +// `&'owner str` and this could further coerce if there're implied outlives, e.g. +// `&'earlier_field &'owner ()` would allow `&'owner str` to further coerce to `&'earlier_field`. +// +// Thus, if any self-referential field require field lifetime access in `Drop` impl, we would need +// to ensure that the all generic parameters visible by self-referential fields would strictly +// outlive the struct. And this can be done by a simple `Drop` impl that does nothing. Without a +// dropck eye patch, presence of `Drop` impl, albeit empty, tells the drop check that the strict +// outlive relation is needed. +impl Drop for Borrowed { + #[inline(always)] + fn drop(&mut self) {} +} + impl Deref for Borrowed { type Target = T;