Skip to content

Commit 9493caa

Browse files
committed
improve safety comments with additional safety docs in pin-init module
Signed-off-by: Liam Davis <[email protected]>
1 parent f2451d9 commit 9493caa

File tree

3 files changed

+68
-19
lines changed

3 files changed

+68
-19
lines changed

src/__internal.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ where
5151
///
5252
/// # Safety
5353
///
54-
/// Only the `init` module is allowed to use this trait.
54+
/// Implementers (typically the `#[pin_data]` macro) must ensure that this method
55+
/// returns a `PinData` instance that accurately reflects the structural pinning
56+
/// and field layout of `Self`. Incorrect metadata can lead to undefined behavior
57+
/// when used by the `pin-init` macros.
5558
pub unsafe trait HasPinData {
5659
type PinData: PinData;
5760

@@ -63,7 +66,12 @@ pub unsafe trait HasPinData {
6366
///
6467
/// # Safety
6568
///
66-
/// Only the `init` module is allowed to use this trait.
69+
/// This `unsafe trait` is implemented by the `#[pin_data]` macro for its generated metadata
70+
/// struct (e.g., `__ThePinData`). The macro MUST ensure `Self` is `Copy`.
71+
/// It must also ensure `Self::Datee` is the correct struct type implementing
72+
/// `HasPinData<PinData = Self>`. Moreover, the macro must generate sound field accessors
73+
/// on `Self` that uphold their safety contracts and correctly use `$crate::PinInit::__pinned_init`
74+
/// or `$crate::Init::__init`. For internal `pin-init` use only.
6775
pub unsafe trait PinData: Copy {
6876
type Datee: ?Sized + HasPinData;
6977

@@ -81,19 +89,24 @@ pub unsafe trait PinData: Copy {
8189
///
8290
/// # Safety
8391
///
84-
/// Only the `init` module is allowed to use this trait.
92+
/// Implementers (typically the `#[pin_data]` macro) must ensure that this method
93+
/// returns a `PinData` instance that accurately reflects the structural pinning
94+
/// and field layout of `Self`. Incorrect metadata can lead to undefined behavior
95+
/// when used by the `pin-init` macros.
8596
pub unsafe trait HasInitData {
8697
type InitData: InitData;
8798

88-
#[expect(clippy::missing_safety_doc)]
8999
unsafe fn __init_data() -> Self::InitData;
90100
}
91101

92102
/// Same function as `PinData`, but for arbitrary data.
93103
///
94104
/// # Safety
95105
///
96-
/// Only the `init` module is allowed to use this trait.
106+
/// This `unsafe trait` is a component of the `pin-init` macro system.
107+
/// Implementers must ensure `Self` is `Copy`, and`Self::Datee` correctly corresponds to the type
108+
/// `Self` represents for initialization purposes. This trait is primarily intended for internal use
109+
/// by the `pin-init` crate.
97110
pub unsafe trait InitData: Copy {
98111
type Datee: ?Sized + HasInitData;
99112

@@ -116,12 +129,16 @@ impl<T: ?Sized> Clone for AllData<T> {
116129

117130
impl<T: ?Sized> Copy for AllData<T> {}
118131

119-
// SAFETY: TODO.
132+
// SAFETY: This implementation upholds the `InitData` invariants that `AllData<T>` is `Copy`, and
133+
// `Self::Datee` is `T`, which correctly represents the type `AllData<T>` is concerned with
134+
// for initialization, as used by the `pin_init!` macros. The `make_closure` method is inherited
135+
// and is a safe identity function, fulfilling trait expectations.
120136
unsafe impl<T: ?Sized> InitData for AllData<T> {
121137
type Datee = T;
122138
}
123139

124-
// SAFETY: TODO.
140+
// SAFETY: `__init_data` returns `AllData<T>` which is a correct `InitData` implementation
141+
// for type `T`. The function itself performs no unsafe memory operations.
125142
unsafe impl<T: ?Sized> HasInitData for T {
126143
type InitData = AllData<T>;
127144

src/lib.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,10 @@ macro_rules! stack_try_pin_init {
763763
///
764764
/// let init = pin_init!(&this in Buf {
765765
/// buf: [0; 64],
766-
/// // SAFETY: TODO.
766+
/// // SAFETY: `this.as_ptr()` (within `pin_init!(&this in ...)` context) yields a `*mut Buf`
767+
/// // that the macro guarantees is valid for initialization (non-null, aligned, points to memory for `Buf`).
768+
/// // This makes it dereferenceable for `addr_of_mut!`, which safely creates a raw pointer to the `buf` field,
769+
/// // even if uninitialized, as it avoids creating a reference.
767770
/// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },
768771
/// pin: PhantomPinned,
769772
/// });
@@ -1390,19 +1393,19 @@ where
13901393
unsafe { pin_init_from_closure(init) }
13911394
}
13921395

1393-
// SAFETY: Every type can be initialized by-value.
1396+
// SAFETY: TODO.
13941397
unsafe impl<T, E> Init<T, E> for T {
13951398
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
1396-
// SAFETY: TODO.
1399+
// SAFETY: `slot` points to a valid, uninitialized memory of the correct size and alignment for type `T`.
13971400
unsafe { slot.write(self) };
13981401
Ok(())
13991402
}
14001403
}
14011404

1402-
// SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`.
1405+
// SAFETY: TODO.
14031406
unsafe impl<T, E> PinInit<T, E> for T {
14041407
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1405-
// SAFETY: TODO.
1408+
// SAFETY: `self` is a valid value of type `T`, and all requirements for `__init` are met.
14061409
unsafe { self.__init(slot) }
14071410
}
14081411
}

src/macros.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,11 @@ macro_rules! __pinned_drop {
518518
}
519519
),
520520
) => {
521-
// SAFETY: TODO.
521+
// SAFETY: This macro generates the `unsafe impl PinnedDrop`. This is safe as it's
522+
// an internal part of the `#[pinned_drop]` proc-macro, which ensures correct
523+
// transformation of the user's `impl`. The added `OnlyCallFromDrop` token restricts
524+
// `PinnedDrop::drop` calls to the actual drop process (via the `Drop::drop` impl
525+
// generated by `#[pin_data(PinnedDrop)]`) where `self` is pinned and valid.
522526
unsafe $($impl_sig)* {
523527
// Inherit all attributes and the type/ident tokens for the signature.
524528
$(#[$($attr)*])*
@@ -878,7 +882,12 @@ macro_rules! __pin_data {
878882
}
879883
}
880884

881-
// SAFETY: TODO.
885+
// SAFETY: The `__pin_data` macro ensures this `impl PinData` for `__ThePinData` is
886+
// safe by guaranteeing that `__ThePinData` is `Copy`, `PinData::Datee` is correctly
887+
// set to `$name` (which itself implements `HasPinData<PinData = __ThePinData>`), and
888+
// that all generated field accessor methods on `__ThePinData` are sound, uphold their
889+
// individual safety contracts (such as ensuring valid `slot` pointers), and correctly
890+
// use either `$crate::PinInit::__pinned_init` or `$crate::Init::__init`.
882891
unsafe impl<$($impl_generics)*>
883892
$crate::__internal::PinData for __ThePinData<$($ty_generics)*>
884893
where $($whr)*
@@ -1000,23 +1009,32 @@ macro_rules! __pin_data {
10001009
{
10011010
$(
10021011
$(#[$($p_attr)*])*
1012+
/// # Safety
1013+
///
1014+
/// The caller must ensure that `slot` is a valid pointer to uninitialized memory
1015+
/// that is properly aligned and large enough to hold a value of type `$p_type`.
10031016
$pvis unsafe fn $p_field<E>(
10041017
self,
10051018
slot: *mut $p_type,
10061019
init: impl $crate::PinInit<$p_type, E>,
10071020
) -> ::core::result::Result<(), E> {
1008-
// SAFETY: TODO.
1021+
// SAFETY: `slot` points to valid, uninitialized memory for a `$p_type`.
10091022
unsafe { $crate::PinInit::__pinned_init(init, slot) }
10101023
}
10111024
)*
10121025
$(
10131026
$(#[$($attr)*])*
1027+
/// # Safety
1028+
///
1029+
/// The caller must ensure that `slot` is a valid pointer to uninitialized memory
1030+
/// that is properly aligned and large enough to hold a value of type `$type`.
1031+
/// The memory at `slot` must also be valid for writes.
10141032
$fvis unsafe fn $field<E>(
10151033
self,
10161034
slot: *mut $type,
10171035
init: impl $crate::Init<$type, E>,
10181036
) -> ::core::result::Result<(), E> {
1019-
// SAFETY: TODO.
1037+
// SAFETY: `slot` points to valid, uninitialized memory for a `$type`.
10201038
unsafe { $crate::Init::__init(init, slot) }
10211039
}
10221040
)*
@@ -1132,7 +1150,12 @@ macro_rules! __init_internal {
11321150
struct __InitOk;
11331151
// Get the data about fields from the supplied type.
11341152
//
1135-
// SAFETY: TODO.
1153+
// SAFETY: The `$get_data()` call (which resolves to either `HasPinData::__pin_data()`
1154+
// or `HasInitData::__init_data()`) is safe because the `#[pin_data]` macro, when applied
1155+
// to type `$t`, correctly implements the respective trait. This ensures that the returned
1156+
// metadata accurately reflects `$t`'s structure and pinning properties, fulfilling the
1157+
// `# Safety` contract of the called `__pin_data()` or `__init_data()` method.
1158+
// The `paste!` macro is used for re-tokenization and does not affect this safety argument.
11361159
let data = unsafe {
11371160
use $crate::__internal::$has_data;
11381161
// Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
@@ -1188,7 +1211,12 @@ macro_rules! __init_internal {
11881211
let init = move |slot| -> ::core::result::Result<(), $err> {
11891212
init(slot).map(|__InitOk| ())
11901213
};
1191-
// SAFETY: TODO.
1214+
// SAFETY: The `init` closure, generated by this macro, upholds the contract of
1215+
// `$crate::$construct_closure`. It ensures `slot` is fully initialized on `Ok(())`
1216+
// or properly cleaned (via `DropGuard`s) on `Err(err)`, leaving `slot` safe to
1217+
// deallocate. Pinning invariants are maintained using `PinData`/`InitData` methods
1218+
// for field initialization, and `slot` is not moved (for `!Unpin` types) as it's
1219+
// accessed via a pointer.
11921220
let init = unsafe { $crate::$construct_closure::<_, $err>(init) };
11931221
init
11941222
}};
@@ -1338,7 +1366,8 @@ macro_rules! __init_internal {
13381366
// Since we are in the closure that is never called, this will never get executed.
13391367
// We abuse `slot` to get the correct type inference here:
13401368
//
1341-
// SAFETY: TODO.
1369+
// SAFETY: This is unreachable code that is used solely for compile-time type checking,
1370+
// it is never executed.
13421371
unsafe {
13431372
// Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
13441373
// information that is associated to already parsed fragments, so a path fragment

0 commit comments

Comments
 (0)