From 9f74336bc95dc8c839cdf46a064c04919310d014 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Tue, 25 May 2021 11:31:48 +0100 Subject: [PATCH] pyfunction: better error message with `async fn` --- pyo3-macros-backend/src/pyfunction.rs | 3 ++- pyo3-macros-backend/src/pymethod.rs | 2 ++ pyo3-macros-backend/src/utils.rs | 11 +++++++++++ tests/ui/invalid_pyfunctions.rs | 3 +++ tests/ui/invalid_pyfunctions.stderr | 8 ++++++++ tests/ui/invalid_pymethods.rs | 5 +++++ tests/ui/invalid_pymethods.stderr | 8 ++++++++ 7 files changed, 39 insertions(+), 1 deletion(-) diff --git a/pyo3-macros-backend/src/pyfunction.rs b/pyo3-macros-backend/src/pyfunction.rs index e61eebef..c1851e69 100644 --- a/pyo3-macros-backend/src/pyfunction.rs +++ b/pyo3-macros-backend/src/pyfunction.rs @@ -8,7 +8,7 @@ use crate::{ deprecations::Deprecations, method::{self, FnArg, FnSpec}, pymethod::{check_generic, get_arg_names, impl_arg_params}, - utils, + utils::{self, ensure_not_async_fn}, }; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote}; @@ -349,6 +349,7 @@ pub fn impl_wrap_pyfunction( options: PyFunctionOptions, ) -> syn::Result<(Ident, TokenStream)> { check_generic(&func.sig)?; + ensure_not_async_fn(&func.sig)?; let python_name = options .name diff --git a/pyo3-macros-backend/src/pymethod.rs b/pyo3-macros-backend/src/pymethod.rs index ebb85aab..5748d01c 100644 --- a/pyo3-macros-backend/src/pymethod.rs +++ b/pyo3-macros-backend/src/pymethod.rs @@ -1,3 +1,4 @@ +use crate::utils::ensure_not_async_fn; // Copyright (c) 2017-present PyO3 Project and Contributors use crate::{attributes::FromPyWithAttribute, konst::ConstSpec}; use crate::{deprecations::Deprecations, utils}; @@ -28,6 +29,7 @@ pub fn gen_py_method( options: PyFunctionOptions, ) -> Result { check_generic(sig)?; + ensure_not_async_fn(sig)?; let spec = FnSpec::parse(sig, &mut *meth_attrs, options)?; Ok(match &spec.tp { diff --git a/pyo3-macros-backend/src/utils.rs b/pyo3-macros-backend/src/utils.rs index 991361c9..7242e96b 100644 --- a/pyo3-macros-backend/src/utils.rs +++ b/pyo3-macros-backend/src/utils.rs @@ -164,3 +164,14 @@ pub fn get_doc( Ok(syn::LitStr::new(&doc, span)) } + +pub fn ensure_not_async_fn(sig: &syn::Signature) -> syn::Result<()> { + if let Some(asyncness) = &sig.asyncness { + bail_spanned!( + asyncness.span() => "`async fn` is not yet supported for Python functions.\n\n\ + Additional crates such as `pyo3-asyncio` can be used to integrate async Rust and \ + Python. For more information, see https://github.com/PyO3/pyo3/issues/1632" + ); + }; + Ok(()) +} diff --git a/tests/ui/invalid_pyfunctions.rs b/tests/ui/invalid_pyfunctions.rs index c58ef70f..680ca56e 100644 --- a/tests/ui/invalid_pyfunctions.rs +++ b/tests/ui/invalid_pyfunctions.rs @@ -6,4 +6,7 @@ fn generic_function(value: T) {} #[pyfunction] fn impl_trait_function(impl_trait: impl AsRef) {} +#[pyfunction] +async fn async_function() {} + fn main() {} diff --git a/tests/ui/invalid_pyfunctions.stderr b/tests/ui/invalid_pyfunctions.stderr index 161f856e..38d73d72 100644 --- a/tests/ui/invalid_pyfunctions.stderr +++ b/tests/ui/invalid_pyfunctions.stderr @@ -9,3 +9,11 @@ error: Python functions cannot have `impl Trait` arguments | 7 | fn impl_trait_function(impl_trait: impl AsRef) {} | ^^^^ + +error: `async fn` is not yet supported for Python functions. + +Additional crates such as `pyo3-asyncio` can be used to integrate async Rust and Python. For more information, see https://github.com/PyO3/pyo3/issues/1632 + --> $DIR/invalid_pyfunctions.rs:10:1 + | +10 | async fn async_function() {} + | ^^^^^ diff --git a/tests/ui/invalid_pymethods.rs b/tests/ui/invalid_pymethods.rs index a082ccc0..43e7c838 100644 --- a/tests/ui/invalid_pymethods.rs +++ b/tests/ui/invalid_pymethods.rs @@ -103,4 +103,9 @@ impl MyClass { fn impl_trait_method_second_arg(&self, impl_trait: impl AsRef) {} } +#[pymethods] +impl MyClass { + async fn async_method(&self) {} +} + fn main() {} diff --git a/tests/ui/invalid_pymethods.stderr b/tests/ui/invalid_pymethods.stderr index 04c8a05e..c1ec13c6 100644 --- a/tests/ui/invalid_pymethods.stderr +++ b/tests/ui/invalid_pymethods.stderr @@ -87,3 +87,11 @@ error: Python functions cannot have `impl Trait` arguments | 103 | fn impl_trait_method_second_arg(&self, impl_trait: impl AsRef) {} | ^^^^ + +error: `async fn` is not yet supported for Python functions. + +Additional crates such as `pyo3-asyncio` can be used to integrate async Rust and Python. For more information, see https://github.com/PyO3/pyo3/issues/1632 + --> $DIR/invalid_pymethods.rs:108:5 + | +108 | async fn async_method(&self) {} + | ^^^^^