mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
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 <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-5-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
This commit is contained in:
parent
73511e489b
commit
29213c00cc
|
|
@ -473,6 +473,35 @@ unsafe impl<F: EraseLt> Sync for Erase<F>
|
|||
#[repr(transparent)]
|
||||
pub struct Borrowed<T: ?Sized>(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<T: ?Sized> Drop for Borrowed<T> {
|
||||
#[inline(always)]
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Deref for Borrowed<T> {
|
||||
type Target = T;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user