Merge branch 'master' into gc-default
This commit is contained in:
commit
9c961b4248
|
@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
|
||||
### Changed
|
||||
|
||||
* Implementing the Using the `gc` parameter for `pyclass` (e.g. `#[pyclass(gc)]`) without implementing the `class::PyGCProtocol` trait is now a compile-time error. Failing to implement this trait could lead to segfaults. [#532](https://github.com/PyO3/pyo3/pull/532)
|
||||
|
||||
## [0.7.0] - 2018-05-26
|
||||
|
||||
### Added
|
||||
|
|
|
@ -573,9 +573,16 @@ impl PyGCProtocol for ClassWithGCSupport {
|
|||
|
||||
Special protocol trait implementations have to be annotated with the `#[pyproto]` attribute.
|
||||
|
||||
It is also possible to enable GC for custom class using the `gc` parameter of the `pyclass` attribute.
|
||||
It is also possible to enable GC for custom classes using the `gc` parameter of the `pyclass` attribute.
|
||||
i.e. `#[pyclass(gc)]`. In that case instances of custom class participate in Python garbage
|
||||
collection, and it is possible to track them with `gc` module methods.
|
||||
collection, and it is possible to track them with `gc` module methods. When using the `gc` parameter,
|
||||
it is *required* to implement the `PyGCProtocol` trait, failure to do so will result in an error
|
||||
at compile time:
|
||||
|
||||
```compile_fail
|
||||
#[pyclass(gc)]
|
||||
struct GCTracked {} // Fails because it does not implement PyGCProtocol
|
||||
```
|
||||
|
||||
### Iterator Types
|
||||
|
||||
|
|
|
@ -296,12 +296,15 @@ fn impl_class(
|
|||
// insert space for weak ref
|
||||
let mut has_weakref = false;
|
||||
let mut has_dict = false;
|
||||
let mut has_gc = false;
|
||||
for f in attr.flags.iter() {
|
||||
if let syn::Expr::Path(ref epath) = f {
|
||||
if epath.path == parse_quote! {pyo3::type_object::PY_TYPE_FLAG_WEAKREF} {
|
||||
has_weakref = true;
|
||||
} else if epath.path == parse_quote! {pyo3::type_object::PY_TYPE_FLAG_DICT} {
|
||||
has_dict = true;
|
||||
} else if epath.path == parse_quote! {pyo3::type_object::PY_TYPE_FLAG_GC} {
|
||||
has_gc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +324,22 @@ fn impl_class(
|
|||
quote! { None }
|
||||
};
|
||||
|
||||
// Enforce at compile time that PyGCProtocol is implemented
|
||||
let gc_impl = if has_gc {
|
||||
let closure_name = format!("__assertion_closure_{}", cls.to_string());
|
||||
let closure_token = syn::Ident::new(&closure_name, Span::call_site());
|
||||
quote! {
|
||||
fn #closure_token() {
|
||||
use pyo3::class;
|
||||
|
||||
fn _assert_implements_protocol<'p, T: pyo3::class::PyGCProtocol<'p>>() {}
|
||||
_assert_implements_protocol::<#cls>();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
let inventory_impl = impl_inventory(&cls);
|
||||
|
||||
let base = &attr.base;
|
||||
|
@ -365,6 +384,9 @@ fn impl_class(
|
|||
#inventory_impl
|
||||
|
||||
#extra
|
||||
|
||||
#gc_impl
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue