diff --git a/pyo3-macros-backend/src/method.rs b/pyo3-macros-backend/src/method.rs index 62e5079eba4..b1294cb772d 100644 --- a/pyo3-macros-backend/src/method.rs +++ b/pyo3-macros-backend/src/method.rs @@ -481,13 +481,16 @@ impl<'a> FnSpec<'a> { // The method call is necessary to generate a decent error message. let rust_call = quote! { - let ret = #rust_name(#self_arg #(#arg_names),*); + let mut ret = #rust_name(#self_arg #(#arg_names),*); - use _pyo3::callback::IntoPyResult; - let ret: _pyo3::PyResult<_> = ret.into_py_result(); + if false { + use _pyo3::impl_::ghost::IntoPyResult; + ret.into_py_result(); + } _pyo3::callback::convert(#py, ret) }; + let krate = &self.krate; Ok(match self.convention { CallingConvention::Noargs => { diff --git a/src/callback.rs b/src/callback.rs index 9f912a84c67..7b487c48424 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -35,31 +35,6 @@ impl PyCallbackOutput for () { const ERR_VALUE: Self = (); } -/// A helper trait to result-wrap the return values of functions and methods. -#[doc(hidden)] -pub trait IntoPyResult { - fn into_py_result(self) -> R; -} - -impl IntoPyResult> for T -where - T: IntoPy, -{ - fn into_py_result(self) -> PyResult { - Ok(self) - } -} - -impl IntoPyResult> for Result -where - T: IntoPy, - E: Into, -{ - fn into_py_result(self) -> PyResult { - self.map_err(Into::into) - } -} - /// Convert the result of callback function into the appropriate return value. pub trait IntoPyCallbackOutput { fn convert(self, py: Python<'_>) -> PyResult; diff --git a/src/impl_.rs b/src/impl_.rs index 5f27a1fc20f..64ca136062c 100644 --- a/src/impl_.rs +++ b/src/impl_.rs @@ -9,6 +9,7 @@ pub mod extract_argument; pub mod freelist; #[doc(hidden)] pub mod frompyobject; +pub mod ghost; pub(crate) mod not_send; #[doc(hidden)] pub mod pyclass; diff --git a/src/impl_/ghost.rs b/src/impl_/ghost.rs new file mode 100644 index 00000000000..68fd3408112 --- /dev/null +++ b/src/impl_/ghost.rs @@ -0,0 +1,19 @@ +/// If it does nothing, was it ever really there? 👻 +/// +/// This is code that is just type checked to e.g. create better compile errors, +/// but that never affects anything at runtime, +use crate::{IntoPy, PyErr, PyObject}; + +#[allow(clippy::wrong_self_convention)] +pub trait IntoPyResult { + fn into_py_result(&mut self) {} +} + +impl IntoPyResult for T where T: IntoPy {} + +impl IntoPyResult for Result +where + T: IntoPy, + E: Into, +{ +} diff --git a/tests/ui/invalid_result_conversion.stderr b/tests/ui/invalid_result_conversion.stderr index 88bff60ef45..decaa8c72ae 100644 --- a/tests/ui/invalid_result_conversion.stderr +++ b/tests/ui/invalid_result_conversion.stderr @@ -1,12 +1,22 @@ -error[E0599]: the method `into_py_result` exists for enum `Result<(), MyError>`, but its trait bounds were not satisfied +error[E0599]: no method named `into_py_result` found for enum `Result` in the current scope --> tests/ui/invalid_result_conversion.rs:21:1 | 21 | #[pyfunction] - | ^^^^^^^^^^^^^ method cannot be called on `Result<(), MyError>` due to unsatisfied trait bounds + | ^^^^^^^^^^^^^ method not found in `Result<(), MyError>` | - = note: the following trait bounds were not satisfied: - `&Result<(), MyError>: IntoPy>` - which is required by `&Result<(), MyError>: IntoPyResult, PyErr>>` - `&mut Result<(), MyError>: IntoPy>` - which is required by `&mut Result<(), MyError>: IntoPyResult, PyErr>>` = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Result<(), MyError>: IntoPyCallbackOutput<_>` is not satisfied + --> tests/ui/invalid_result_conversion.rs:21:1 + | +21 | #[pyfunction] + | ^^^^^^^^^^^^^ the trait `IntoPyCallbackOutput<_>` is not implemented for `Result<(), MyError>` + | + = help: the following implementations were found: + as IntoPyCallbackOutput> +note: required by a bound in `pyo3::callback::convert` + --> src/callback.rs + | + | T: IntoPyCallbackOutput, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `pyo3::callback::convert` + = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/missing_intopy.stderr b/tests/ui/missing_intopy.stderr index 69da4c3a8e6..f3b71704a18 100644 --- a/tests/ui/missing_intopy.stderr +++ b/tests/ui/missing_intopy.stderr @@ -6,18 +6,14 @@ error[E0599]: the method `into_py_result` exists for struct `Blah`, but its trai | | | method `into_py_result` not found for this | doesn't satisfy `Blah: IntoPy>` - | doesn't satisfy `Blah: IntoPyResult>` + | doesn't satisfy `Blah: IntoPyResult` 2 | 3 | #[pyo3::pyfunction] | ^^^^^^^^^^^^^^^^^^^ method cannot be called on `Blah` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `Blah: IntoPy>` - which is required by `Blah: IntoPyResult>` - `&Blah: IntoPy>` - which is required by `&Blah: IntoPyResult>` - `&mut Blah: IntoPy>` - which is required by `&mut Blah: IntoPyResult>` + which is required by `Blah: IntoPyResult` note: the following trait must be implemented --> src/conversion.rs | @@ -27,3 +23,16 @@ note: the following trait must be implemented | | } | |_^ = note: this error originates in the attribute macro `pyo3::pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Blah: IntoPyCallbackOutput<_>` is not satisfied + --> tests/ui/missing_intopy.rs:3:1 + | +3 | #[pyo3::pyfunction] + | ^^^^^^^^^^^^^^^^^^^ the trait `IntoPyCallbackOutput<_>` is not implemented for `Blah` + | +note: required by a bound in `pyo3::callback::convert` + --> src/callback.rs + | + | T: IntoPyCallbackOutput, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `pyo3::callback::convert` + = note: this error originates in the attribute macro `pyo3::pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)