Merge branch 'master' into gc-default

This commit is contained in:
Yuji Kanagawa 2019-07-15 14:25:27 +09:00 committed by GitHub
commit 9c961b4248
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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
}
}