diff --git a/src/conversion.rs b/src/conversion.rs index 68c0cd9c..665d7e2d 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -290,6 +290,10 @@ pub trait PyTryFrom<'v>: Sized + PyNativeType { /// Cast a PyAny to a specific type of PyObject. The caller must /// have already verified the reference is for this type. + /// + /// # Safety + /// + /// Callers must ensure that the type is valid or risk type confusion. unsafe fn try_from_unchecked>(value: V) -> &'v Self; } @@ -387,24 +391,64 @@ impl IntoPy> for () { /// Raw level conversion between `*mut ffi::PyObject` and PyO3 types. pub unsafe trait FromPyPointer<'p>: Sized { + /// Convert from an arbitrary `PyObject`. + /// + /// # Safety + /// + /// Implementations must ensure the object does not get freed during `'p` and avoid type confusion. unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self>; + /// Convert from an arbitrary `PyObject` or panic. + /// + /// # Safety + /// + /// Relies on unsafe fn `from_owned_ptr_or_opt`. unsafe fn from_owned_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self { Self::from_owned_ptr_or_opt(py, ptr).unwrap_or_else(|| err::panic_after_error(py)) } + /// Convert from an arbitrary `PyObject` or panic. + /// + /// # Safety + /// + /// Relies on unsafe fn `from_owned_ptr_or_opt`. unsafe fn from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self { Self::from_owned_ptr_or_panic(py, ptr) } + /// Convert from an arbitrary `PyObject`. + /// + /// # Safety + /// + /// Relies on unsafe fn `from_owned_ptr_or_opt`. unsafe fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyResult<&'p Self> { Self::from_owned_ptr_or_opt(py, ptr).ok_or_else(|| err::PyErr::fetch(py)) } + /// Convert from an arbitrary borrowed `PyObject`. + /// + /// # Safety + /// + /// Implementations must ensure the object does not get freed during `'p` and avoid type confusion. unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self>; + /// Convert from an arbitrary borrowed `PyObject`. + /// + /// # Safety + /// + /// Relies on unsafe fn `from_borrowed_ptr_or_opt`. unsafe fn from_borrowed_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self { Self::from_borrowed_ptr_or_opt(py, ptr).unwrap_or_else(|| err::panic_after_error(py)) } + /// Convert from an arbitrary borrowed `PyObject`. + /// + /// # Safety + /// + /// Relies on unsafe fn `from_borrowed_ptr_or_opt`. unsafe fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self { Self::from_borrowed_ptr_or_panic(py, ptr) } + /// Convert from an arbitrary borrowed `PyObject`. + /// + /// # Safety + /// + /// Relies on unsafe fn `from_borrowed_ptr_or_opt`. unsafe fn from_borrowed_ptr_or_err( py: Python<'p>, ptr: *mut ffi::PyObject, diff --git a/src/instance.rs b/src/instance.rs index 573bea58..6f3a8c46 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -356,6 +356,9 @@ impl Py { } /// Deprecated alias for [`from_owned_ptr`](#method.from_owned_ptr). + /// + /// # Safety + /// `ptr` must be a pointer to a Python object of type T. #[inline] #[deprecated = "this is a deprecated alias for Py::from_owned_ptr"] pub unsafe fn from_owned_ptr_or_panic(py: Python, ptr: *mut ffi::PyObject) -> Py { diff --git a/src/python.rs b/src/python.rs index 90a7127e..9dc4c55d 100644 --- a/src/python.rs +++ b/src/python.rs @@ -448,6 +448,10 @@ impl<'p> Python<'p> { /// Registers the object in the release pool, and does an unchecked downcast /// to the specific type. + /// + /// # Safety + /// + /// Callers must ensure that ensure that the cast is valid. pub unsafe fn cast_as(self, obj: PyObject) -> &'p T where T: PyNativeType + PyTypeInfo, @@ -458,6 +462,10 @@ impl<'p> Python<'p> { /// Registers the object pointer in the release pool, /// and does an unchecked downcast to the specific type. + /// + /// # Safety + /// + /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention)] pub unsafe fn from_owned_ptr(self, ptr: *mut ffi::PyObject) -> &'p T where @@ -470,6 +478,10 @@ impl<'p> Python<'p> { /// /// Returns `Err(PyErr)` if the pointer is NULL. /// Does an unchecked downcast to the specific type. + /// + /// # Safety + /// + /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention)] pub unsafe fn from_owned_ptr_or_err(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T> where @@ -482,6 +494,10 @@ impl<'p> Python<'p> { /// /// Returns `None` if the pointer is NULL. /// Does an unchecked downcast to the specific type. + /// + /// # Safety + /// + /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention)] pub unsafe fn from_owned_ptr_or_opt(self, ptr: *mut ffi::PyObject) -> Option<&'p T> where @@ -493,6 +509,10 @@ impl<'p> Python<'p> { /// Does an unchecked downcast to the specific type. /// /// Panics if the pointer is NULL. + /// + /// # Safety + /// + /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention)] pub unsafe fn from_borrowed_ptr(self, ptr: *mut ffi::PyObject) -> &'p T where @@ -504,6 +524,10 @@ impl<'p> Python<'p> { /// Does an unchecked downcast to the specific type. /// /// Returns `Err(PyErr)` if the pointer is NULL. + /// + /// # Safety + /// + /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention)] pub unsafe fn from_borrowed_ptr_or_err(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T> where @@ -515,6 +539,10 @@ impl<'p> Python<'p> { /// Does an unchecked downcast to the specific type. /// /// Returns `None` if the pointer is NULL. + /// + /// # Safety + /// + /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention)] pub unsafe fn from_borrowed_ptr_or_opt(self, ptr: *mut ffi::PyObject) -> Option<&'p T> where diff --git a/src/types/bytes.rs b/src/types/bytes.rs index ab5b1329..3b8c6741 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -67,6 +67,10 @@ impl PyBytes { /// Creates a new Python byte string object from a raw pointer and length. /// /// Panics if out of memory. + /// + /// # Safety + /// + /// Unsafe as it deferences the raw pointer `ptr`. pub unsafe fn from_ptr(py: Python<'_>, ptr: *const u8, len: usize) -> &PyBytes { py.from_owned_ptr(ffi::PyBytes_FromStringAndSize( ptr as *const _,