diff --git a/newsfragments/5964.added.md b/newsfragments/5964.added.md new file mode 100644 index 00000000000..4ca26732cd9 --- /dev/null +++ b/newsfragments/5964.added.md @@ -0,0 +1,2 @@ +Add `PySequence_FAST_GET_SIZE` and `PySequence_FAST_GET_ITEM`, +and convert `PyObject_CallOneArg` and `PyVectorcall_Function` to regular functions starting in 3.11. diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index b6358f854ff..1c3b962b7cb 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -6,10 +6,13 @@ use std::ffi::c_int; #[cfg(not(Py_3_11))] use crate::Py_buffer; +#[cfg(all(not(Py_3_11), not(PyPy)))] +use crate::{PyCallable_Check, PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL}; + #[cfg(not(PyPy))] use crate::{ - vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check, - PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL, + vectorcallfunc, PyList_Check, PyList_GET_ITEM, PyList_GET_SIZE, PyThreadState, + PyThreadState_GET, PyTuple_Check, PyTuple_GET_ITEM, PyTuple_GET_SIZE, }; use libc::size_t; @@ -49,7 +52,7 @@ pub unsafe fn PyVectorcall_NARGS(n: size_t) -> Py_ssize_t { n.try_into().expect("cannot fail due to mask") } -#[cfg(not(PyPy))] +#[cfg(all(not(Py_3_11), not(PyPy)))] #[inline(always)] pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option { assert!(!callable.is_null()); @@ -64,6 +67,11 @@ pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option Option; +} + #[cfg(not(PyPy))] #[inline(always)] pub unsafe fn _PyObject_VectorcallTstate( @@ -161,7 +169,7 @@ extern_libpython! { pub fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject; } -#[cfg(not(PyPy))] +#[cfg(all(not(Py_3_11), not(PyPy)))] #[inline(always)] pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject { assert!(!arg.is_null()); @@ -172,6 +180,11 @@ pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *m _PyObject_VectorcallTstate(tstate, func, args, nargsf, std::ptr::null_mut()) } +extern_libpython! { + #[cfg(all(Py_3_11, not(PyPy)))] + pub fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject; +} + #[cfg(all(Py_3_9, not(PyPy)))] #[inline(always)] pub unsafe fn PyObject_CallMethodNoArgs( @@ -275,6 +288,28 @@ extern_libpython! { // skipped PySequence_ITEM +#[cfg(not(PyPy))] +#[inline(always)] +pub unsafe fn PySequence_FAST_GET_SIZE(o: *mut PyObject) -> Py_ssize_t { + let is_list = PyList_Check(o) != 0; + if is_list { + PyList_GET_SIZE(o) + } else { + PyTuple_GET_SIZE(o) + } +} + +#[cfg(not(PyPy))] +#[inline(always)] +pub unsafe fn PySequence_FAST_GET_ITEM(o: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { + let is_list = PyList_Check(o) != 0; + if is_list { + PyList_GET_ITEM(o, i) + } else { + PyTuple_GET_ITEM(o, i) + } +} + pub const PY_ITERSEARCH_COUNT: c_int = 1; pub const PY_ITERSEARCH_INDEX: c_int = 2; pub const PY_ITERSEARCH_CONTAINS: c_int = 3;