From 9838006319554dc45c8f119b6a809c244d6c045e Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sat, 11 Apr 2026 13:09:19 -0400 Subject: [PATCH 1/8] Add support for PyList and PyTuple in vectorcall functions --- pyo3-ffi/src/cpython/abstract_.rs | 39 ++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index b6358f854ff..eb55dc16947 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -8,7 +8,8 @@ use crate::Py_buffer; #[cfg(not(PyPy))] use crate::{ - vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check, + vectorcallfunc, PyCallable_Check, PyList_Check, PyList_GET_ITEM, PyList_GET_SIZE, + PyThreadState, PyThreadState_GET, PyTuple_Check, PyTuple_GET_ITEM, PyTuple_GET_SIZE, PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL, }; use libc::size_t; @@ -49,7 +50,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 +65,11 @@ pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option Option +} + #[cfg(not(PyPy))] #[inline(always)] pub unsafe fn _PyObject_VectorcallTstate( @@ -161,7 +167,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 +178,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 unsafe 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 +286,28 @@ extern_libpython! { // skipped PySequence_ITEM +#[cfg(all(Py_3_9, 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(all(Py_3_9, 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; From 1f78e13cb735975f2e8cbb6fa500651b615706fc Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sat, 11 Apr 2026 13:11:10 -0400 Subject: [PATCH 2/8] Add new functions and convert existing ones for 3.11 Add new functions and update existing ones for Python 3.11 compatibility. --- newsfragments/5964.added.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 newsfragments/5964.added.md 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. From 023c473783b9f885591fedee3e6b24daed6fcb0f Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sat, 11 Apr 2026 13:12:23 -0400 Subject: [PATCH 3/8] Fix syntax error in PyVectorcall_Function declaration --- pyo3-ffi/src/cpython/abstract_.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index eb55dc16947..95194aad4b0 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -67,7 +67,7 @@ pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option Option + pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option; } #[cfg(not(PyPy))] From 0cccd62d37ed253d4f9af24d664f76da34a6d830 Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sat, 11 Apr 2026 13:15:00 -0400 Subject: [PATCH 4/8] Remove unsafe from PyVectorcall_Function and PyObject_CallOneArg --- pyo3-ffi/src/cpython/abstract_.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index 95194aad4b0..1cc63299ccf 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -67,7 +67,7 @@ pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option Option; + pub fn PyVectorcall_Function(callable: *mut PyObject) -> Option; } #[cfg(not(PyPy))] @@ -180,7 +180,7 @@ pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *m extern_libpython! { #[cfg(all(Py_3_11, not(PyPy)))] - pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject; + pub fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject; } #[cfg(all(Py_3_9, not(PyPy)))] From 3484cb8711d942bef446e7bffb284a2fc9b566b3 Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sat, 11 Apr 2026 13:19:53 -0400 Subject: [PATCH 5/8] Add conditional import for PyCallable_Check and features --- pyo3-ffi/src/cpython/abstract_.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index 1cc63299ccf..e46e0b95ec0 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -6,11 +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, PyList_Check, PyList_GET_ITEM, PyList_GET_SIZE, + vectorcallfunc, PyList_Check, PyList_GET_ITEM, PyList_GET_SIZE, PyThreadState, PyThreadState_GET, PyTuple_Check, PyTuple_GET_ITEM, PyTuple_GET_SIZE, - PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL, }; use libc::size_t; From a5474e93d25cca6778efd803b704e9a6fddfdedc Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sat, 11 Apr 2026 13:22:40 -0400 Subject: [PATCH 6/8] fmt --- pyo3-ffi/src/cpython/abstract_.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index e46e0b95ec0..831a1de7532 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -11,8 +11,8 @@ use crate::{PyCallable_Check, PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL}; #[cfg(not(PyPy))] use crate::{ - vectorcallfunc, PyList_Check, PyList_GET_ITEM, PyList_GET_SIZE, - PyThreadState, PyThreadState_GET, PyTuple_Check, PyTuple_GET_ITEM, PyTuple_GET_SIZE, + vectorcallfunc, PyList_Check, PyList_GET_ITEM, PyList_GET_SIZE, PyThreadState, + PyThreadState_GET, PyTuple_Check, PyTuple_GET_ITEM, PyTuple_GET_SIZE, }; use libc::size_t; From b1f925df9fed686521ae63a8817fce6f809c1165 Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sat, 11 Apr 2026 13:52:25 -0400 Subject: [PATCH 7/8] Update configuration flags for PySequence functions --- pyo3-ffi/src/cpython/abstract_.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index 831a1de7532..f156bb568ed 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -288,7 +288,7 @@ extern_libpython! { // skipped PySequence_ITEM -#[cfg(all(Py_3_9, not(PyPy)))] +#[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; @@ -299,7 +299,7 @@ pub unsafe fn PySequence_FAST_GET_SIZE(o: *mut PyObject) -> Py_ssize_t { } } -#[cfg(all(Py_3_9, not(PyPy)))] +#[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; From 128a7a860f54b8a0bb45b47d1f7d383f2e36b66f Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Sat, 11 Apr 2026 13:53:16 -0400 Subject: [PATCH 8/8] Fix syntax error in configuration attribute --- pyo3-ffi/src/cpython/abstract_.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index f156bb568ed..1c3b962b7cb 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -299,7 +299,7 @@ pub unsafe fn PySequence_FAST_GET_SIZE(o: *mut PyObject) -> Py_ssize_t { } } -#[cfg(not(PyPy)] +#[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;