-
Notifications
You must be signed in to change notification settings - Fork 905
Description
Following the introduction of the Bound API in 0.21, we have converged on three primary traits which are used to convert Rust datatypes to Python.
- one trait for from-Python conversions:
FromPyObject - two traits for to-Python conversions:
ToPyObjectandIntoPy<PyObject>(and sub-formsIntoPy<Py<PyTuple>>andIntoPy<Py<PyString>>)
There are several opportunities to contribute to PyO3 with a goal of improving these traits. Given that these traits are so central to PyO3's API, they impact developer ergonomics and performance. The right designs could improve PyO3 a lot, though any new API would need a migration pathway which is feasible for users.
Improving FromPyObject
FromPyObject is already in a migration state as its input argument is changing from a GIL Ref to a Bound smart pointer. We also have FromPyObjectBound which allows a few additional optimisations and extractions like &str at cost of complexity. We think the two lifetimes of FromPyObjectBound will be the future design of FromPyObject, though we don't yet know how that will interact with #[derive(FromPyObject)].
Beyond resolving that question, I am aware of at least two other possibilities to refine FromPyObject:
- Rather than returning
PyErras the error type, we could do something similar tostd::str::FromStrand add atype Errassociated type. This would allow implementations to use just downcasting errors, or other concrete Rust errors without having to go through the relatively heavyPyErrmachinery. - In Review conversions and ensure consistency #3226 and similar issues we have discussed how there is a possibility to define either "strict" or "lax" conversions. Maybe
FromPyObjectcould have anextract_exactmethod added, which defines strict conversions, so that the#[pyfunction]macros can have a#[pyo3(exact)]annotation on arguments to control this better.
Improving to-Python traits
I'm reasonably convinced that there doesn't need to be two (or four, depending how you see it) to-Python traits for PyO3.
In addition, we have a strong need to have a fallible conversion, because there are now several panics inside PyO3 which are caused by the limitation that none of these traits can fail.
I once proposed an IntoPyObject trait in #2316. If FromPyObject is staying around, I think IntoPyObject is the right name to pair with it (though maybe we just introduce a new trait for each direction, for easier migration). I think the design in #2316 is outdated and also it probably should be fallible, as FromPyObject is also fallible.
Maybe the following is closer to the right definition:
trait IntoPyObject {
type Target;
type Err;
fn into_pyobject(self, py: Python<'py>) -> Result<Bound<'py, Self::Target>, Self::Err>;
}... but that's just a sketch, and discussion / research / prototyping would yield valuable insight.