From 5096f936dc55486592a2df14eaca6a54270dac4c Mon Sep 17 00:00:00 2001 From: konstin Date: Mon, 15 Jul 2019 12:45:16 +0200 Subject: [PATCH] Disable segfaulty subclassing by default See https://github.com/PyO3/pyo3/issues/220 and https://github.com/PyO3/pyo3/issues/407 for details on those segfaults --- CHANGELOG.md | 4 ++++ Cargo.toml | 3 +++ examples/rustapi_module/Cargo.toml | 2 +- guide/src/class.md | 2 +- pyo3-derive-backend/Cargo.toml | 3 +++ pyo3-derive-backend/src/pyclass.rs | 6 ++++++ pyo3cls/Cargo.toml | 3 +++ tests/test_inheritance.rs | 3 +++ 8 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 814e07d1..190458a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. * Use existing fields and methods before calling custom __getattr__. [#505](https://github.com/PyO3/pyo3/pull/512) * `PyBytes` can now be indexed just like `Vec` +## Removed + + * `#[pyclass(subclass)]` is hidden a `unsound-subclass` feature because it's causing segmentation faults. + ### Fixed * More readable error message for generics in pyclass [#503](https://github.com/PyO3/pyo3/pull/503) diff --git a/Cargo.toml b/Cargo.toml index 7ded547b..c60bc9ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,9 @@ extension-module = [] # are welcome. # abi3 = [] +# Activate subclassing support +unsound-subclass = ["pyo3cls/unsound-subclass"] + [workspace] members = [ "pyo3cls", diff --git a/examples/rustapi_module/Cargo.toml b/examples/rustapi_module/Cargo.toml index 98e728ee..7490e95a 100644 --- a/examples/rustapi_module/Cargo.toml +++ b/examples/rustapi_module/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" [dependencies.pyo3] path = "../../" -features = ["extension-module"] +features = ["extension-module", "unsound-subclass"] [lib] name = "rustapi_module" diff --git a/guide/src/class.md b/guide/src/class.md index 988ff314..128d51a3 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -102,10 +102,10 @@ so that they can benefit from a freelist. `XXX` is a number of items for the fre If a custom class contains references to other Python objects that can be collected, the `PyGCProtocol` trait has to be implemented. * `weakref` - Adds support for Python weak references. * `extends=BaseType` - Use a custom base class. The base `BaseType` must implement `PyTypeInfo`. -* `subclass` - Allows Python classes to inherit from this class. * `dict` - Adds `__dict__` support, so that the instances of this type have a dictionary containing arbitrary instance variables. * `module="XXX"` - Set the name of the module the class will be shown as defined in. If not given, the class will be a virtual member of the `builtins` module. +* `subclass` - Allows Python classes to inherit from this class. This feature is hidden behind a `unsound-subclass` feature because it is currently causing segmentation faults ## Constructor diff --git a/pyo3-derive-backend/Cargo.toml b/pyo3-derive-backend/Cargo.toml index dbfdac19..87f48d8b 100644 --- a/pyo3-derive-backend/Cargo.toml +++ b/pyo3-derive-backend/Cargo.toml @@ -14,3 +14,6 @@ edition = "2018" quote = "0.6.12" proc-macro2 = "0.4.30" syn = { version = "0.15.34", features = ["full", "extra-traits"] } + +[features] +unsound-subclass = [] diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 5e7841e6..c5d0221f 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -132,6 +132,12 @@ impl PyClassArgs { parse_quote! {pyo3::type_object::PY_TYPE_FLAG_WEAKREF} } "subclass" => { + if cfg!(not(feature = "unsound-subclass")) { + return Err(syn::Error::new_spanned( + exp.path.clone(), + "You need to activate the `unsound-subclass` feature if you want to use subclassing", + )); + } parse_quote! {pyo3::type_object::PY_TYPE_FLAG_BASETYPE} } "dict" => { diff --git a/pyo3cls/Cargo.toml b/pyo3cls/Cargo.toml index 5630c8cd..b31dc700 100644 --- a/pyo3cls/Cargo.toml +++ b/pyo3cls/Cargo.toml @@ -18,3 +18,6 @@ quote= "0.6.12" proc-macro2 = "0.4.30" syn = { version = "0.15.34", features = ["full", "extra-traits"] } pyo3-derive-backend = { path = "../pyo3-derive-backend", version = "=0.7.0" } + +[features] +unsound-subclass = ["pyo3-derive-backend/unsound-subclass"] diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rs index c34c072a..69f70c64 100644 --- a/tests/test_inheritance.rs +++ b/tests/test_inheritance.rs @@ -1,5 +1,6 @@ use pyo3::prelude::*; use pyo3::py_run; +#[cfg(feature = "unsound-subclass")] use pyo3::types::IntoPyDict; use std::isize; @@ -11,9 +12,11 @@ struct BaseClass { val1: usize, } +#[cfg(feature = "unsound-subclass")] #[pyclass(subclass)] struct SubclassAble {} +#[cfg(feature = "unsound-subclass")] #[test] fn subclass() { let gil = Python::acquire_gil();