Skip to content

Commit 0912b79

Browse files
add: add unsafe doc for src/internal
1 parent fd4f03e commit 0912b79

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

src/internal/get_slot.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub(crate) unsafe fn get_slot<const S: c_int>(
5151
where
5252
Slot<S>: GetSlotImpl,
5353
{
54+
// SAFETY: caller guarantees
5455
unsafe {
5556
slot.get_slot(
5657
ty,
@@ -95,7 +96,8 @@ macro_rules! impl_slots {
9596
) -> Self::Type {
9697
#[cfg(not(Py_LIMITED_API))]
9798
{
98-
unsafe {(*ty).$field }
99+
// SAFETY: caller guarantees
100+
unsafe { (*ty).$field }
99101
}
100102

101103
#[cfg(Py_LIMITED_API)]
@@ -109,6 +111,7 @@ macro_rules! impl_slots {
109111
// of the type objects for these historical versions.
110112
if !is_runtime_3_10 && unsafe {ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE)} == 0
111113
{
114+
// SAFETY: see above comment.
112115
return unsafe {(*ty.cast::<PyTypeObject39Snapshot>()).$field};
113116
}
114117
}

src/internal/state.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ impl AttachGuard {
7070
Err(AttachError::NotInitialized) => {
7171
// try to initialize the interpreter and try again
7272
crate::interpreter_lifecycle::ensure_initialized();
73+
// SAFETY: The interpreter is now initialized and the thread is not attached.
7374
unsafe { Self::do_attach_unchecked() }
7475
}
7576
#[cfg(Py_3_13)]
@@ -127,9 +128,12 @@ impl AttachGuard {
127128
/// for a thread to be able to attach to it.
128129
pub(crate) unsafe fn attach_unchecked() -> Self {
129130
if thread_is_attached() {
131+
// SAFETY: We just checked that the thread is already attached.
132+
// And the caller promised that the interpreter is initialized.
130133
return unsafe { Self::assume() };
131134
}
132135

136+
// SAFETY: The caller promised that the interpreter is initialized.
133137
unsafe { Self::do_attach_unchecked() }
134138
}
135139

@@ -166,6 +170,7 @@ impl Drop for AttachGuard {
166170
fn drop(&mut self) {
167171
match self {
168172
AttachGuard::Assumed => {}
173+
// SAFETY: we are dropping an `AttachGuard` that previously called `PyGILState_Ensure`
169174
AttachGuard::Ensured { gstate } => unsafe {
170175
// Drop the objects in the pool before attempting to release the thread state
171176
ffi::PyGILState_Release(*gstate);
@@ -206,14 +211,17 @@ impl ReferencePool {
206211
drop(pending_decrefs);
207212

208213
for ptr in decrefs {
214+
// SAFETY: `ptr` is a valid owned reference that was registered via `register_decref`.
209215
unsafe { ffi::Py_DECREF(ptr.as_ptr()) };
210216
}
211217
}
212218
}
213219

220+
// SAFETY: `ReferencePool` only contains a `Mutex`
214221
#[cfg(not(pyo3_disable_reference_pool))]
215222
unsafe impl Send for ReferencePool {}
216223

224+
// SAFETY: `ReferencePool` only contains a `Mutex`
217225
#[cfg(not(pyo3_disable_reference_pool))]
218226
unsafe impl Sync for ReferencePool {}
219227

@@ -243,6 +251,7 @@ pub(crate) struct SuspendAttach {
243251
impl SuspendAttach {
244252
pub(crate) unsafe fn new() -> Self {
245253
let count = ATTACH_COUNT.with(|c| c.replace(0));
254+
// SAFETY: caller must ensure the thread is currently attached.
246255
let tstate = unsafe { ffi::PyEval_SaveThread() };
247256

248257
Self { count, tstate }
@@ -252,6 +261,9 @@ impl SuspendAttach {
252261
impl Drop for SuspendAttach {
253262
fn drop(&mut self) {
254263
ATTACH_COUNT.with(|c| c.set(self.count));
264+
// SAFETY: `self.tstate` is a valid thread state that was saved by `PyEval_SaveThread()`
265+
// in `SuspendAttach::new()`. We restore the attach count before calling
266+
// `PyEval_RestoreThread`, so `Python::assume_attached()` is valid after the restore.
255267
unsafe {
256268
ffi::PyEval_RestoreThread(self.tstate);
257269

0 commit comments

Comments
 (0)