Skip to content

Commit

Permalink
PyPy: the PyList_GET/SET macros are defined as functions, the PyTuple…
Browse files Browse the repository at this point in the history
…_ ones do not exist
  • Loading branch information
birkenfeld committed Jul 4, 2021
1 parent 9cdb6a0 commit f723548
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

- Implement `IntoPy<PyObject>` for `&PathBuf` and `&OsString`. [#1721](https://github.com/PyO3/pyo3/pull/1712)

### Fixed

- Fix crashes on PyPy due to incorrect definitions of `PyList_SET_ITEM`. [#1713](https://github.com/PyO3/pyo3/pull/1713)

## [0.14.0] - 2021-07-03

### Packaging
Expand Down
3 changes: 3 additions & 0 deletions src/ffi/cpython/listobject.rs
Expand Up @@ -15,17 +15,20 @@ pub struct PyListObject {

/// Macro, trading safety for speed
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyList_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject {
*(*(op as *mut PyListObject)).ob_item.offset(i as isize)
}

/// Macro, *only* to be used to fill in brand new lists
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyList_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) {
*(*(op as *mut PyListObject)).ob_item.offset(i as isize) = v;
}

#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyList_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {
Py_SIZE(op)
}
11 changes: 11 additions & 0 deletions src/ffi/listobject.rs
Expand Up @@ -52,4 +52,15 @@ extern "C" {
pub fn PyList_Reverse(arg1: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyList_AsTuple")]
pub fn PyList_AsTuple(arg1: *mut PyObject) -> *mut PyObject;

// CPython macros exported as functions on PyPy
#[cfg(PyPy)]
#[cfg_attr(PyPy, link_name = "PyPyList_GET_ITEM")]
pub fn PyList_GET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject;
#[cfg(PyPy)]
#[cfg_attr(PyPy, link_name = "PyPyList_GET_SIZE")]
pub fn PyList_GET_SIZE(arg1: *mut PyObject) -> Py_ssize_t;
#[cfg(PyPy)]
#[cfg_attr(PyPy, link_name = "PyPyList_SET_ITEM")]
pub fn PyList_SET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject);
}
6 changes: 3 additions & 3 deletions src/ffi/tupleobject.rs
Expand Up @@ -47,7 +47,7 @@ extern "C" {

/// Macro, trading safety for speed
#[inline]
#[cfg(not(Py_LIMITED_API))]
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject {
*(*(op as *mut PyTupleObject))
.ob_item
Expand All @@ -56,14 +56,14 @@ pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObjec
}

#[inline]
#[cfg(not(Py_LIMITED_API))]
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
pub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {
Py_SIZE(op)
}

/// Macro, *only* to be used to fill in brand new tuples
#[inline]
#[cfg(not(Py_LIMITED_API))]
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
pub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) {
*(*(op as *mut PyTupleObject))
.ob_item
Expand Down
12 changes: 6 additions & 6 deletions src/types/tuple.rs
Expand Up @@ -26,9 +26,9 @@ impl PyTuple {
unsafe {
let ptr = ffi::PyTuple_New(len as Py_ssize_t);
for (i, e) in elements_iter.enumerate() {
#[cfg(not(Py_LIMITED_API))]
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
ffi::PyTuple_SET_ITEM(ptr, i as Py_ssize_t, e.to_object(py).into_ptr());
#[cfg(Py_LIMITED_API)]
#[cfg(any(Py_LIMITED_API, PyPy))]
ffi::PyTuple_SetItem(ptr, i as Py_ssize_t, e.to_object(py).into_ptr());
}
py.from_owned_ptr(ptr)
Expand All @@ -43,9 +43,9 @@ impl PyTuple {
/// Gets the length of the tuple.
pub fn len(&self) -> usize {
unsafe {
#[cfg(not(Py_LIMITED_API))]
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
let size = ffi::PyTuple_GET_SIZE(self.as_ptr());
#[cfg(Py_LIMITED_API)]
#[cfg(any(Py_LIMITED_API, PyPy))]
let size = ffi::PyTuple_Size(self.as_ptr());
// non-negative Py_ssize_t should always fit into Rust uint
size as usize
Expand Down Expand Up @@ -79,9 +79,9 @@ impl PyTuple {
pub fn get_item(&self, index: usize) -> &PyAny {
assert!(index < self.len());
unsafe {
#[cfg(not(Py_LIMITED_API))]
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
let item = ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t);
#[cfg(Py_LIMITED_API)]
#[cfg(any(Py_LIMITED_API, PyPy))]
let item = ffi::PyTuple_GetItem(self.as_ptr(), index as Py_ssize_t);

self.py().from_borrowed_ptr(item)
Expand Down

0 comments on commit f723548

Please sign in to comment.