-
Notifications
You must be signed in to change notification settings - Fork 886
Description
Bug Description
Rust supports recursive enums if they have an indirection, e.g., the following is supported by Rust
enum E {
A(i64),
B(String),
C(Vec<E>),
}
This shows up for me in a custom serialization format, but JSON would have the same use case.
Separately, when PyO3 sees an enum decorated with #[pyclass]
which derives Clone
it will automatically implement FromPyObject
which allows converting from Python types which is especially useful for huge Rust enums. This seems to be slightly broken for enums, but it seems one can also derive FromPyObject
which will automatically implement Clone
, e.g.,
#[derive(FromPyObject, Eq, PartialEq)]
#[pyclass(eq)]
enum E {
A(i64),
B(String),
// C(Vec<E>), // HERE.
}
#[pyfunction]
fn make_e(e: E) -> E {
e
}
generates a factory function for E
which can be used in Python to convert from supported types, e.g.,
from my_crate import E, make_e
assert make_e(1) == E.A(1)
assert make_e("2") == E.B("2")
If I want to add variant C
which is commented out above, the existing derives do not work anymore and the code is rejected at compile time with
--> src/lib.rs:15:7
|
15 | C(Vec<E>), // HERE.
| ^^^^^^ the trait `Clone` is not implemented for `E`
|
= note: required for `Vec<E>` to implement `Clone`
= note: required for `Vec<E>` to implement `PyO3GetField<'_>`
note: required by a bound in `ConvertField::<false, IMPLEMENTS_INTOPYOBJECT>::convert_field`
If I change the derive to #[derive(Clone, Eq, PartialEq)]
the code compiles again, but the generated FromPyObject
implementation seems broken
$ python bla.py
File "bla.py", line 3, in <module>
assert make_e(1) == E.A(1)
TypeError: argument 'e': 'int' object cannot be converted to 'E'
I however cannot implement it myself since an implementation already exist, so the current macro seems fundamentally broken and the only workaround might be to implement PyClass
, PyTypeInfo
, FromPyObject
, and IntoPyObject
by hand.
Steps to Reproduce
See above.
Backtrace
Your operating system and version
macos-15.6.1
Your Python version (python --version
)
Python 3.9.20
Your Rust version (rustc --version
)
rustc 1.90.0 (1159e78c4 2025-09-14)
Your PyO3 version
0.26.0
How did you install python? Did you use a virtualenv?
via rye and requires-python = ">=3.9"
in my pyproject.toml
Additional Info
No response