Inhibit __ipow__ to take Modulo

This commit is contained in:
kngwyu 2020-03-30 03:01:44 +09:00
parent 25eda36353
commit ac418ce020
4 changed files with 13 additions and 15 deletions

View File

@ -602,10 +602,9 @@ pub const NUM: Proto = Proto {
pyres: false, pyres: false,
proto: "pyo3::class::number::PyNumberIModProtocol", proto: "pyo3::class::number::PyNumberIModProtocol",
}, },
MethodProto::Ternary { MethodProto::Binary {
name: "__ipow__", name: "__ipow__",
arg1: "Other", arg: "Other",
arg2: "Modulo",
pyres: false, pyres: false,
proto: "pyo3::class::number::PyNumberIPowProtocol", proto: "pyo3::class::number::PyNumberIPowProtocol",
}, },

View File

@ -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] #[macro_export]
#[doc(hidden)] #[doc(hidden)]
macro_rules! py_ternary_self_func { macro_rules! py_dummy_ternary_self_func {
($trait:ident, $class:ident :: $f:ident) => {{ ($trait:ident, $class:ident :: $f:ident) => {{
unsafe extern "C" fn wrap<T>( unsafe extern "C" fn wrap<T>(
slf: *mut $crate::ffi::PyObject, slf: *mut $crate::ffi::PyObject,
arg1: *mut $crate::ffi::PyObject, arg1: *mut $crate::ffi::PyObject,
arg2: *mut $crate::ffi::PyObject, _arg2: *mut $crate::ffi::PyObject,
) -> *mut $crate::ffi::PyObject ) -> *mut $crate::ffi::PyObject
where where
T: for<'p> $trait<'p>, T: for<'p> $trait<'p>,
@ -318,20 +320,18 @@ macro_rules! py_ternary_self_func {
let py = $crate::Python::assume_gil_acquired(); let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py); let _pool = $crate::GILPool::new(py);
let slf_cell = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf); let slf_ = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg2); let result = call_mut!(slf_, $f, arg);
let result = call_mut!(slf_cell, $f, arg1, arg2);
match result { match result {
Ok(_) => { Ok(_) => {
// Without this INCREF, SIGSEGV happens...
ffi::Py_INCREF(slf); ffi::Py_INCREF(slf);
slf slf
} }
Err(e) => e.restore_and_null(py), Err(e) => e.restore_and_null(py),
} }
} }
Some(wrap::<T>) Some(wrap::<$class>)
}}; }};
} }

View File

@ -224,7 +224,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
{ {
unimplemented!() unimplemented!()
} }
fn __ipow__(&'p mut self, other: Self::Other, modulo: Option<Self::Modulo>) -> Self::Result fn __ipow__(&'p mut self, other: Self::Other) -> Self::Result
where where
Self: PyNumberIPowProtocol<'p>, Self: PyNumberIPowProtocol<'p>,
{ {
@ -544,7 +544,6 @@ pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> {
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Modulo: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: Into<PyResult<()>>;
} }
@ -1280,7 +1279,7 @@ where
T: for<'p> PyNumberIPowProtocol<'p>, T: for<'p> PyNumberIPowProtocol<'p>,
{ {
fn nb_inplace_power() -> Option<ffi::ternaryfunc> { fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
py_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__) py_dummy_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__)
} }
} }

View File

@ -121,7 +121,7 @@ impl PyNumberProtocol for InPlaceOperations {
Ok(()) Ok(())
} }
fn __ipow__(&mut self, other: u32, _mod: Option<u32>) -> PyResult<()> { fn __ipow__(&mut self, other: u32) -> PyResult<()> {
self.value = self.value.pow(other); self.value = self.value.pow(other);
Ok(()) Ok(())
} }