Merge pull request #966 from davidhewitt/pyclass-send

Require Send for #[pyclass] (no compilefail test)
This commit is contained in:
Yuji Kanagawa 2020-06-09 19:25:54 +09:00 committed by GitHub
commit 7a7271319c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 17 additions and 24 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Simplify internals of `#[pyo3(get)]` attribute. (Remove the hidden API `GetPropertyValue`.) [#934](https://github.com/PyO3/pyo3/pull/934)
- Call `Py_Finalize` at exit to flush buffers, etc. [#943](https://github.com/PyO3/pyo3/pull/943)
- Add type parameter to PyBuffer. #[951](https://github.com/PyO3/pyo3/pull/951)
- Require `Send` bound for `#[pyclass]`. [#966](https://github.com/PyO3/pyo3/pull/966)
### Removed
- Remove `ManagedPyRef` (unused, and needs specialization) [#930](https://github.com/PyO3/pyo3/pull/930)

View File

@ -14,10 +14,9 @@ struct MyClass {
}
```
The above example generates implementations for [`PyTypeInfo`], [`PyTypeObject`],
and [`PyClass`] for `MyClass`.
Because Python objects are freely shared between threads by the Python interpreter, all structs annotated with `#[pyclass]` must implement `Send`.
If you curious what `#[pyclass]` generates, see [How methods are implemented](#how-methods-are-implemented) section.
The above example generates implementations for [`PyTypeInfo`], [`PyTypeObject`], and [`PyClass`] for `MyClass`. To see these generated implementations, refer to the section [How methods are implemented](#how-methods-are-implemented) at the end of this chapter.
## Adding the class to a module

View File

@ -72,7 +72,9 @@ pub unsafe fn tp_free_fallback(obj: *mut ffi::PyObject) {
///
/// The `#[pyclass]` attribute automatically implements this trait for your Rust struct,
/// so you don't have to use this trait directly.
pub trait PyClass: PyTypeInfo<Layout = PyCell<Self>> + Sized + PyClassAlloc + PyMethods {
pub trait PyClass:
PyTypeInfo<Layout = PyCell<Self>> + Sized + PyClassAlloc + PyMethods + Send
{
/// Specify this class has `#[pyclass(dict)]` or not.
type Dict: PyClassDict;
/// Specify this class has `#[pyclass(weakref)]` or not.

View File

@ -4,7 +4,6 @@ use pyo3::class::PyVisit;
use pyo3::prelude::*;
use pyo3::type_object::PyTypeObject;
use pyo3::{py_run, AsPyPointer, PyCell, PyTryInto};
use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
@ -84,19 +83,19 @@ fn data_is_dropped() {
#[allow(dead_code)]
#[pyclass]
struct GCIntegration {
self_ref: RefCell<PyObject>,
self_ref: PyObject,
dropped: TestDropCall,
}
#[pyproto]
impl PyGCProtocol for GCIntegration {
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
visit.call(&*self.self_ref.borrow())
visit.call(&self.self_ref)
}
fn __clear__(&mut self) {
let gil = GILGuard::acquire();
*self.self_ref.borrow_mut() = gil.python().None();
self.self_ref = gil.python().None();
}
}
@ -110,7 +109,7 @@ fn gc_integration() {
let inst = PyCell::new(
py,
GCIntegration {
self_ref: RefCell::new(py.None()),
self_ref: py.None(),
dropped: TestDropCall {
drop_called: Arc::clone(&drop_called),
},
@ -119,7 +118,7 @@ fn gc_integration() {
.unwrap();
let mut borrow = inst.borrow_mut();
*borrow.self_ref.borrow_mut() = inst.to_object(py);
borrow.self_ref = inst.to_object(py);
}
let gil = Python::acquire_gil();

View File

@ -1,17 +1,9 @@
use pyo3::prelude::*;
use pyo3::types::PyList;
#[pyclass]
struct MyClass {
list: &'static PyList,
}
#[pymethods]
impl MyClass {
#[new]
fn new(list: &'static PyList) -> Self {
Self { list }
}
#[pyfunction]
fn static_ref(list: &'static PyList) -> usize {
list.len()
}
fn main() {}

View File

@ -1,8 +1,8 @@
error[E0597]: `pool` does not live long enough
--> $DIR/static_ref.rs:9:1
--> $DIR/static_ref.rs:4:1
|
9 | #[pymethods]
| ^^^^^^^^^^^^
4 | #[pyfunction]
| ^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| `pool` dropped here while still borrowed