From ac418ce02099ed2cabe1ba4d49c809cf4839756a Mon Sep 17 00:00:00 2001 From: kngwyu Date: Mon, 30 Mar 2020 03:01:44 +0900 Subject: [PATCH] Inhibit __ipow__ to take Modulo --- pyo3-derive-backend/src/defs.rs | 5 ++--- src/class/macros.rs | 16 ++++++++-------- src/class/number.rs | 5 ++--- tests/test_arithmetics.rs | 2 +- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs index 43b4f06f..02a5ca74 100644 --- a/pyo3-derive-backend/src/defs.rs +++ b/pyo3-derive-backend/src/defs.rs @@ -602,10 +602,9 @@ pub const NUM: Proto = Proto { pyres: false, proto: "pyo3::class::number::PyNumberIModProtocol", }, - MethodProto::Ternary { + MethodProto::Binary { name: "__ipow__", - arg1: "Other", - arg2: "Modulo", + arg: "Other", pyres: false, proto: "pyo3::class::number::PyNumberIPowProtocol", }, diff --git a/src/class/macros.rs b/src/class/macros.rs index e2735939..a7de4c9b 100644 --- a/src/class/macros.rs +++ b/src/class/macros.rs @@ -302,14 +302,16 @@ macro_rules! py_ternary_reverse_num_func { }}; } +// NOTE(kngwyu): Somehow __ipow__ causes SIGSEGV in Python < 3.8 when we extract arg2, +// so we ignore it. It's the same as what CPython does. #[macro_export] #[doc(hidden)] -macro_rules! py_ternary_self_func { +macro_rules! py_dummy_ternary_self_func { ($trait:ident, $class:ident :: $f:ident) => {{ unsafe extern "C" fn wrap( slf: *mut $crate::ffi::PyObject, arg1: *mut $crate::ffi::PyObject, - arg2: *mut $crate::ffi::PyObject, + _arg2: *mut $crate::ffi::PyObject, ) -> *mut $crate::ffi::PyObject where T: for<'p> $trait<'p>, @@ -318,20 +320,18 @@ macro_rules! py_ternary_self_func { let py = $crate::Python::assume_gil_acquired(); let _pool = $crate::GILPool::new(py); - let slf_cell = py.from_borrowed_ptr::<$crate::PyCell>(slf); - let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); - let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg2); - let result = call_mut!(slf_cell, $f, arg1, arg2); + let slf_ = py.from_borrowed_ptr::<$crate::PyCell>(slf); + let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg1); + let result = call_mut!(slf_, $f, arg); match result { Ok(_) => { - // Without this INCREF, SIGSEGV happens... ffi::Py_INCREF(slf); slf } Err(e) => e.restore_and_null(py), } } - Some(wrap::) + Some(wrap::<$class>) }}; } diff --git a/src/class/number.rs b/src/class/number.rs index 68079489..b845d2e0 100644 --- a/src/class/number.rs +++ b/src/class/number.rs @@ -224,7 +224,7 @@ pub trait PyNumberProtocol<'p>: PyClass { { unimplemented!() } - fn __ipow__(&'p mut self, other: Self::Other, modulo: Option) -> Self::Result + fn __ipow__(&'p mut self, other: Self::Other) -> Self::Result where Self: PyNumberIPowProtocol<'p>, { @@ -544,7 +544,6 @@ pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> { type Other: FromPyObject<'p>; - type Modulo: FromPyObject<'p>; type Result: Into>; } @@ -1280,7 +1279,7 @@ where T: for<'p> PyNumberIPowProtocol<'p>, { fn nb_inplace_power() -> Option { - py_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__) + py_dummy_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__) } } diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rs index c5de341e..2072ae04 100755 --- a/tests/test_arithmetics.rs +++ b/tests/test_arithmetics.rs @@ -121,7 +121,7 @@ impl PyNumberProtocol for InPlaceOperations { Ok(()) } - fn __ipow__(&mut self, other: u32, _mod: Option) -> PyResult<()> { + fn __ipow__(&mut self, other: u32) -> PyResult<()> { self.value = self.value.pow(other); Ok(()) }