From f92af23b197821d961cfc39b28d858cd46afc66a Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Mon, 6 Jan 2025 00:04:31 -0800 Subject: [PATCH] macros: charecterization tests for ? operator fail When a `?` operator is used in a tokio entry point function (wrapped in `#[tokio::main]`), which has a Option or Result return type, but where the function does not actually return that type correctly, currently the compiler returns two errors instead of just one. The first of which is incorrect and only exists due to the macro expanding to an async block. ``` cannot use the `?` operator in an async block that returns `()` ``` This commit is a characterization test for this behavior to help show when it's fixed (or even changed for better / worse) --- .../tests/fail/macros_type_mismatch.rs | 34 ++++++++++ .../tests/fail/macros_type_mismatch.stderr | 65 +++++++++++++++++-- 2 files changed, 95 insertions(+), 4 deletions(-) diff --git a/tests-build/tests/fail/macros_type_mismatch.rs b/tests-build/tests/fail/macros_type_mismatch.rs index c292ee68f66..fbb15be4332 100644 --- a/tests-build/tests/fail/macros_type_mismatch.rs +++ b/tests-build/tests/fail/macros_type_mismatch.rs @@ -23,6 +23,40 @@ async fn extra_semicolon() -> Result<(), ()> { Ok(()); } +/// This test is a charecterization test for the `?` operator. +/// +/// See for more details. +/// +/// It should fail with a single error message about the return type of the function, but instead +/// if fails with an extra error message due to the `?` operator being used within the async block +/// rather than the original function. +/// +/// ```text +/// 28 | None?; +/// | ^ cannot use the `?` operator in an async block that returns `()` +/// ``` +#[tokio::main] +async fn question_mark_operator_with_invalid_option() -> Option<()> { + None?; +} + +/// This test is a charecterization test for the `?` operator. +/// +/// See for more details. +/// +/// It should fail with a single error message about the return type of the function, but instead +/// if fails with an extra error message due to the `?` operator being used within the async block +/// rather than the original function. +/// +/// ```text +/// 33 | Ok(())?; +/// | ^ cannot use the `?` operator in an async block that returns `()` +/// ``` +#[tokio::main] +async fn question_mark_operator_with_invalid_result() -> Result<(), ()> { + Ok(())?; +} + // https://github.com/tokio-rs/tokio/issues/4635 #[allow(redundant_semicolons)] #[rustfmt::skip] diff --git a/tests-build/tests/fail/macros_type_mismatch.stderr b/tests-build/tests/fail/macros_type_mismatch.stderr index 579c241559b..201df9cdd05 100644 --- a/tests-build/tests/fail/macros_type_mismatch.stderr +++ b/tests-build/tests/fail/macros_type_mismatch.stderr @@ -49,11 +49,68 @@ help: try adding an expression at the end of the block 24 + Ok(()) | +error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> tests/fail/macros_type_mismatch.rs:40:9 + | +38 | #[tokio::main] + | -------------- this function should return `Result` or `Option` to accept `?` +39 | async fn question_mark_operator_with_invalid_option() -> Option<()> { +40 | None?; + | ^ cannot use the `?` operator in an async block that returns `()` + | + = help: the trait `FromResidual>` is not implemented for `()` + +error[E0308]: mismatched types + --> tests/fail/macros_type_mismatch.rs:40:5 + | +39 | async fn question_mark_operator_with_invalid_option() -> Option<()> { + | ---------- expected `Option<()>` because of return type +40 | None?; + | ^^^^^^ expected `Option<()>`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +40 ~ None?;; +41 + None + | +40 ~ None?;; +41 + Some(()) + | + +error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> tests/fail/macros_type_mismatch.rs:57:11 + | +55 | #[tokio::main] + | -------------- this function should return `Result` or `Option` to accept `?` +56 | async fn question_mark_operator_with_invalid_result() -> Result<(), ()> { +57 | Ok(())?; + | ^ cannot use the `?` operator in an async block that returns `()` + | + = help: the trait `FromResidual>` is not implemented for `()` + +error[E0308]: mismatched types + --> tests/fail/macros_type_mismatch.rs:57:5 + | +56 | async fn question_mark_operator_with_invalid_result() -> Result<(), ()> { + | -------------- expected `Result<(), ()>` because of return type +57 | Ok(())?; + | ^^^^^^^^ expected `Result<(), ()>`, found `()` + | + = note: expected enum `Result<(), ()>` + found unit type `()` +help: try adding an expression at the end of the block + | +57 ~ Ok(())?;; +58 + Ok(()) + | + error[E0308]: mismatched types - --> tests/fail/macros_type_mismatch.rs:32:5 + --> tests/fail/macros_type_mismatch.rs:66:5 | -30 | async fn issue_4635() { +64 | async fn issue_4635() { | - help: try adding a return type: `-> i32` -31 | return 1; -32 | ; +65 | return 1; +66 | ; | ^ expected `()`, found integer