From 212404bc230c5add5a14d72a917235d3bf4230a3 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sat, 16 Oct 2021 18:12:34 +0100 Subject: [PATCH] pymethods: support __rtruediv__ and __rfloordiv__ --- pyo3-macros-backend/src/pyimpl.rs | 6 ++++++ pyo3-macros-backend/src/pymethod.rs | 17 ++++++++--------- src/class/impl_.rs | 20 ++++++++++++++++++++ tests/test_arithmetics.rs | 10 ++++++++++ tests/ui/abi3_nativetype_inheritance.stderr | 8 ++++---- tests/ui/pyclass_send.stderr | 4 ++-- 6 files changed, 50 insertions(+), 15 deletions(-) diff --git a/pyo3-macros-backend/src/pyimpl.rs b/pyo3-macros-backend/src/pyimpl.rs index 18bdcfff..62477289 100644 --- a/pyo3-macros-backend/src/pyimpl.rs +++ b/pyo3-macros-backend/src/pyimpl.rs @@ -176,6 +176,12 @@ fn impl_protos( try_add_shared_slot!("__or__", "__ror__", generate_pyclass_or_slot); try_add_shared_slot!("__xor__", "__rxor__", generate_pyclass_xor_slot); try_add_shared_slot!("__matmul__", "__rmatmul__", generate_pyclass_matmul_slot); + try_add_shared_slot!("__truediv__", "__rtruediv__", generate_pyclass_truediv_slot); + try_add_shared_slot!( + "__floordiv__", + "__rfloordiv__", + generate_pyclass_floordiv_slot + ); try_add_shared_slot!("__pow__", "__rpow__", generate_pyclass_pow_slot); quote! { diff --git a/pyo3-macros-backend/src/pymethod.rs b/pyo3-macros-backend/src/pymethod.rs index 89d94f78..c8c451f0 100644 --- a/pyo3-macros-backend/src/pymethod.rs +++ b/pyo3-macros-backend/src/pymethod.rs @@ -439,13 +439,6 @@ const __INT__: SlotDef = SlotDef::new("Py_nb_int", "unaryfunc"); const __FLOAT__: SlotDef = SlotDef::new("Py_nb_float", "unaryfunc"); const __BOOL__: SlotDef = SlotDef::new("Py_nb_bool", "inquiry").ret_ty(Ty::Int); -const __TRUEDIV__: SlotDef = SlotDef::new("Py_nb_true_divide", "binaryfunc") - .arguments(&[Ty::ObjectOrNotImplemented]) - .extract_error_mode(ExtractErrorMode::NotImplemented); -const __FLOORDIV__: SlotDef = SlotDef::new("Py_nb_floor_divide", "binaryfunc") - .arguments(&[Ty::ObjectOrNotImplemented]) - .extract_error_mode(ExtractErrorMode::NotImplemented); - const __IADD__: SlotDef = SlotDef::new("Py_nb_inplace_add", "binaryfunc") .arguments(&[Ty::ObjectOrNotImplemented]) .extract_error_mode(ExtractErrorMode::NotImplemented) @@ -523,8 +516,6 @@ fn pyproto(method_name: &str) -> Option<&'static SlotDef> { "__int__" => Some(&__INT__), "__float__" => Some(&__FLOAT__), "__bool__" => Some(&__BOOL__), - "__truediv__" => Some(&__TRUEDIV__), - "__floordiv__" => Some(&__FLOORDIV__), "__iadd__" => Some(&__IADD__), "__isub__" => Some(&__ISUB__), "__imul__" => Some(&__IMUL__), @@ -894,6 +885,10 @@ binary_num_slot_fragment_def!(__MUL__, "__mul__"); binary_num_slot_fragment_def!(__RMUL__, "__rmul__"); binary_num_slot_fragment_def!(__MATMUL__, "__matmul__"); binary_num_slot_fragment_def!(__RMATMUL__, "__rmatmul__"); +binary_num_slot_fragment_def!(__FLOORDIV__, "__floordiv__"); +binary_num_slot_fragment_def!(__RFLOORDIV__, "__rfloordiv__"); +binary_num_slot_fragment_def!(__TRUEDIV__, "__truediv__"); +binary_num_slot_fragment_def!(__RTRUEDIV__, "__rtruediv__"); binary_num_slot_fragment_def!(__DIVMOD__, "__divmod__"); binary_num_slot_fragment_def!(__RDIVMOD__, "__rdivmod__"); binary_num_slot_fragment_def!(__MOD__, "__mod__"); @@ -938,6 +933,10 @@ fn pyproto_fragment(method_name: &str) -> Option<&'static SlotFragmentDef> { "__rmul__" => Some(&__RMUL__), "__matmul__" => Some(&__MATMUL__), "__rmatmul__" => Some(&__RMATMUL__), + "__floordiv__" => Some(&__FLOORDIV__), + "__rfloordiv__" => Some(&__RFLOORDIV__), + "__truediv__" => Some(&__TRUEDIV__), + "__rtruediv__" => Some(&__RTRUEDIV__), "__divmod__" => Some(&__DIVMOD__), "__rdivmod__" => Some(&__RDIVMOD__), "__mod__" => Some(&__MOD__), diff --git a/src/class/impl_.rs b/src/class/impl_.rs index de3e5812..125e24a3 100644 --- a/src/class/impl_.rs +++ b/src/class/impl_.rs @@ -415,6 +415,26 @@ define_pyclass_binary_operator_slot! { binaryfunc, } +define_pyclass_binary_operator_slot! { + PyClass__truediv__SlotFragment, + PyClass__rtruediv__SlotFragment, + __truediv__, + __rtruediv__, + generate_pyclass_truediv_slot, + Py_nb_true_divide, + binaryfunc, +} + +define_pyclass_binary_operator_slot! { + PyClass__floordiv__SlotFragment, + PyClass__rfloordiv__SlotFragment, + __floordiv__, + __rfloordiv__, + generate_pyclass_floordiv_slot, + Py_nb_floor_divide, + binaryfunc, +} + slot_fragment_trait! { PyClass__pow__SlotFragment, diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rs index f648ee2e..64649e08 100644 --- a/tests/test_arithmetics.rs +++ b/tests/test_arithmetics.rs @@ -366,6 +366,14 @@ impl LhsAndRhs { fn __rmatmul__(&self, other: &PyAny) -> String { format!("{:?} @ RA", other) } + + fn __rtruediv__(&self, other: &PyAny) -> String { + format!("{:?} / RA", other) + } + + fn __rfloordiv__(&self, other: &PyAny) -> String { + format!("{:?} // RA", other) + } } #[test] @@ -639,6 +647,8 @@ mod return_not_implemented { _test_binary_dunder("rsub"); _test_binary_dunder("rmul"); _test_binary_dunder("rmatmul"); + _test_binary_dunder("rtruediv"); + _test_binary_dunder("rfloordiv"); _test_binary_dunder("rmod"); _test_binary_dunder("rdivmod"); _test_binary_dunder("rpow"); diff --git a/tests/ui/abi3_nativetype_inheritance.stderr b/tests/ui/abi3_nativetype_inheritance.stderr index 51c0d2ab..19296bbe 100644 --- a/tests/ui/abi3_nativetype_inheritance.stderr +++ b/tests/ui/abi3_nativetype_inheritance.stderr @@ -4,9 +4,9 @@ error[E0277]: the trait bound `PyDict: PyClass` is not satisfied 5 | #[pyclass(extends=PyDict)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PyClass` is not implemented for `PyDict` | - ::: src/class/impl_.rs:755:1 + ::: src/class/impl_.rs:775:1 | -755 | pub trait PyClassBaseType: Sized { +775 | pub trait PyClassBaseType: Sized { | -------------------------------- required by this bound in `PyClassBaseType` | = note: required because of the requirements on the impl of `PyClassBaseType` for `PyDict` @@ -18,9 +18,9 @@ error[E0277]: the trait bound `PyDict: PyClass` is not satisfied 5 | #[pyclass(extends=PyDict)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PyClass` is not implemented for `PyDict` | - ::: src/class/impl_.rs:742:47 + ::: src/class/impl_.rs:762:47 | -742 | pub struct ThreadCheckerInherited(PhantomData, U::ThreadChecker); +762 | pub struct ThreadCheckerInherited(PhantomData, U::ThreadChecker); | --------------- required by this bound in `ThreadCheckerInherited` | = note: required because of the requirements on the impl of `PyClassBaseType` for `PyDict` diff --git a/tests/ui/pyclass_send.stderr b/tests/ui/pyclass_send.stderr index c21e7d12..a4228c12 100644 --- a/tests/ui/pyclass_send.stderr +++ b/tests/ui/pyclass_send.stderr @@ -4,9 +4,9 @@ error[E0277]: `Rc` cannot be sent between threads safely 4 | #[pyclass] | ^^^^^^^^^^ `Rc` cannot be sent between threads safely | - ::: src/class/impl_.rs:699:33 + ::: src/class/impl_.rs:719:33 | -699 | pub struct ThreadCheckerStub(PhantomData); +719 | pub struct ThreadCheckerStub(PhantomData); | ---- required by this bound in `ThreadCheckerStub` | = help: within `NotThreadSafe`, the trait `Send` is not implemented for `Rc`