This is a collection of of pyo3 errors I'd like to improve.
Trying to misuse Python::allow_threads.
Code:
use pyo3::prelude::*;
use pyo3::types::PyString;
fn parallel_print(py: Python<'_>) {
let s = PyString::new(py, "This object cannot be accessed without holding the GIL >_<");
py.allow_threads(move || {
println!("{:?}", s); // This causes a compile error.
});
}
Error:
error[E0277]: `UnsafeCell<PyObject>` cannot be shared between threads safely
--> src\lib.rs:6:8
|
6 | py.allow_threads(move || {
| ^^^^^^^^^^^^^ `UnsafeCell<PyObject>` cannot be shared between threads safely
|
= help: within `PyString`, the trait `Sync` is not implemented for `UnsafeCell<PyObject>`
= note: required because it appears within the type `PyAny`
= note: required because it appears within the type `PyString`
= note: required because of the requirements on the impl of `Send` for `&PyString`
= note: required because it appears within the type `[closure@src\lib.rs:6:22: 8:6]`
= note: required because of the requirements on the impl of `Ungil` for `[closure@src\lib.rs:6:22: 8:6]`
note: required by a bound in `pyo3::Python::<'py>::allow_threads`
--> C:\Users\bruno\rust\pyo3\src\marker.rs:450:12
|
450 | F: Ungil + FnOnce() -> T,
| ^^^^^ required by this bound in `pyo3::Python::<'py>::allow_threads`
For more information about this error, try `rustc --explain E0277`.
Improved error:
error[E0277]: the trait bound `PyString: Ungil` is not satisfied in `[closure@src\lib.rs:6:22: 8:6]`
--> src\lib.rs:6:8
|
8 | println!("{:?}", s); // This causes a compile error.
| ^ note: A `PyString` is accessed here...
...
|
6 | py.allow_threads(move || {
| ^^^^^^^^^^^^^---...but the GIL was released here
= note: Python objects are not threadsafe and cannot be used while other Python threads are running.
= note: see <link to guide> for more details.
For more information about this error, try `rustc --explain E0277`.
Missing a tuple argument in e.g. PyAny::call_method1
.
use pyo3::prelude::*;
use pyo3::types::*;
use std::collections::HashMap;
fn foo(py: python<'_>) {
let list = PyList::empty(py);
let map = HashMap::from([("hello", "world")]);
list.call_method1("append", map).unwrap();
}
Error:
error[E0277]: the trait bound `HashMap<&str, &str>: IntoPy<Py<PyTuple>>` is not satisfied
--> src\lib.rs:8:33
|
8 | list.call_method1("append", map).unwrap();
| ------------ ^^^ the trait `IntoPy<Py<PyTuple>>` is not implemented for `HashMap<&str, &str>`
| |
| required by a bound introduced by this call
|
= help: the trait `IntoPy<Py<PyAny>>` is implemented for `HashMap<K, V, H>`
note: required by a bound in `PyAny::call_method1`
--> C:\Users\bruno\rust\pyo3\src\types\any.rs:610:55
|
610 | pub fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> {
|
^^^^^^^^^^^^^^^^^^^ required by this bound in `PyAny::call_method1`
Improved error:
error[E0277]: the trait bound `HashMap<&str, &str>: IntoPy<Py<PyTuple>>` is not satisfied
--> src\lib.rs:8:33
|
8 | list.call_method1("append", map).unwrap();
| ------------ ^^^ the trait `IntoPy<Py<PyTuple>>` is not implemented for `HashMap<&str, &str>`
| |
| required by a bound introduced by this call
|
help: use `(...,)` instead of `(...)` to specify a single-field tuple.
|
8 | list.call_method1("append", (map,)).unwrap();
| + ++
use pyo3::prelude::*;
#[pyclass]
struct MyClass {}
#[pymethods]
impl MyClass {
fn method_with_invalid_self_type(slf: i32, py: Python<'_>, index: u32) {}
}
Error:
error[E0277]: the trait bound `i32: From<&PyCell<MyClass>>` is not satisfied
--> src\lib.rs:8:43
|
8 | fn method_with_invalid_self_type(slf: i32, py: Python<'_>, index: u32) {}
| ^^^ the trait `From<&PyCell<MyClass>>` is not implemented for `i32`
|
= help: the following other types implement trait `From<T>`:
<f32 as From<i16>>
<f32 as From<i8>>
<f32 as From<u16>>
<f32 as From<u8>>
<f64 as From<f32>>
<f64 as From<i16>>
<f64 as From<i32>>
<f64 as From<i8>>
and 67 others
= note: required because of the requirements on the impl of `Into<i32>` for `&PyCell<MyClass>`
= note: required because of the requirements on the impl of `TryFrom<&PyCell<MyClass>>` for `i32`
For more information about this error, try `rustc --explain E0277`.
Improved error:
error[E0277]: the trait bound `i32: From<&PyCell<MyClass>>` is not satisfied
--> src\lib.rs:8:43
|
8 | fn method_with_invalid_self_type(slf: i32, py: Python<'_>, index: u32) {}
| ^^^ the trait `From<&PyCell<MyClass>>` is not implemented for `i32`
|
= help: use one of the valid receiver types: `&self`, `&mut self, `slf: PyRef<'_, Self>` or `slf: PyRefMut<'_, Self>`.
|
8 | fn method_with_invalid_self_type(&self, py: Python<'_>, index: u32) {}
| +++++
|
= help: declare `method_with_invalid_self_type` as a static method
|
| #[staticmethod]
| ++++++++++++++
8 | fn method_with_invalid_self_type(slf: i32, py: Python<'_>, index: u32) {}
|
For more information about this error, try `rustc --explain E0277`.
An example I've seen in the wild is trying to use
HashMap<Py<PyAny>, _>
as the input to a#[pyfunction]
. TheFromPyObject
trait isn't satisfied for this.After staring at it for a while I realised it's because
Py<PyAny>
doesn't implementHash
, however nowhere in the error message was this mentioned last time I looked.