Skip to content

Commit

Permalink
Emit a better error for abi3 inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
mejrs committed May 14, 2024
1 parent 10152a7 commit 7e688b5
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 0 deletions.
4 changes: 4 additions & 0 deletions pyo3-build-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ pub fn print_feature_cfgs() {
if rustc_minor_version >= 74 {
println!("cargo:rustc-cfg=invalid_from_utf8_lint");
}

if rustc_minor_version >= 78 {
println!("cargo:rustc-cfg=diagnostic_namespace");
}
}

/// Registers `pyo3`s config names as reachable cfg expressions
Expand Down
6 changes: 6 additions & 0 deletions src/impl_/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,12 @@ impl<T> PyClassThreadChecker<T> for ThreadCheckerImpl {
}

/// Trait denoting that this class is suitable to be used as a base type for PyClass.
#[cfg_attr(
all(diagnostic_namespace, feature = "abi3"),
diagnostic::on_unimplemented(
note = "with the `abi3` feature enabled native types cannot be subclassed"
)
)]
pub trait PyClassBaseType: Sized {
type LayoutAsBase: PyClassObjectLayout<Self>;
type BaseNativeType;
Expand Down
10 changes: 10 additions & 0 deletions tests/diagnostic_namespace/abi3_inheritance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use pyo3::exceptions::PyException;
use pyo3::prelude::*;

#[pyclass(extends=PyException)]
#[derive(Clone)]
struct MyException {
code: u32,
}

fn main() {}
24 changes: 24 additions & 0 deletions tests/diagnostic_namespace/abi3_inheritance.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0277]: the trait bound `PyException: PyClassBaseType` is not satisfied
--> tests/diagnostic_namespace/abi3_inheritance.rs:4:19
|
4 | #[pyclass(extends=PyException)]
| ^^^^^^^^^^^ the trait `PyClass` is not implemented for `PyException`, which is required by `PyException: PyClassBaseType`
|
= note: with the `abi3` feature enabled native types cannot be subclassed
= help: the trait `PyClassBaseType` is implemented for `PyAny`
= note: required for `PyException` to implement `PyClassBaseType`
note: required by a bound in `PyClassImpl::BaseType`
--> src/impl_/pyclass.rs
|
| type BaseType: PyTypeInfo + PyClassBaseType;
| ^^^^^^^^^^^^^^^ required by this bound in `PyClassImpl::BaseType`

error[E0277]: the trait bound `PyException: PyClass` is not satisfied
--> tests/diagnostic_namespace/abi3_inheritance.rs:4:1
|
4 | #[pyclass(extends=PyException)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PyClass` is not implemented for `PyException`, which is required by `PyException: PyClassBaseType`
|
= help: the trait `PyClass` is implemented for `MyException`
= note: required for `PyException` to implement `PyClassBaseType`
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)
8 changes: 8 additions & 0 deletions tests/test_compile_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,11 @@ fn test_compile_errors() {
t.compile_fail("tests/ui/invalid_cancel_handle.rs");
t.pass("tests/ui/pymodule_missing_docs.rs");
}

#[cfg(all(diagnostic_namespace, not(target_arch = "wasm32")))] // Not possible to invoke compiler from wasm
#[test]
fn test_diagnostics() {
let t = trybuild::TestCases::new();
#[cfg(all(feature = "abi3", not(feature = "experimental-async")))] // output changes with async feature
t.compile_fail("tests/diagnostic_namespace/abi3_inheritance.rs");
}

0 comments on commit 7e688b5

Please sign in to comment.