From c8b71ef3dd83f1d6b99d128ff2fc3b99c9ce28ab Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 12 Oct 2024 06:11:11 -0400 Subject: [PATCH] Also note for fields --- compiler/rustc_hir_typeck/src/expr.rs | 28 +++++++++++++++++------ tests/ui/async-await/field-in-sync.rs | 13 +++++++++++ tests/ui/async-await/field-in-sync.stderr | 17 ++++++++++++++ tests/ui/async-await/issue-61076.stderr | 4 ++-- 4 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 tests/ui/async-await/field-in-sync.rs create mode 100644 tests/ui/async-await/field-in-sync.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b310398a0f1ba..bd35a3a8e8891 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -10,7 +10,8 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordMap; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, StashKey, Subdiagnostic, pluralize, struct_span_code_err, + Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, Subdiagnostic, pluralize, + struct_span_code_err, }; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -2757,12 +2758,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field_ident.span, "field not available in `impl Future`, but it is available in its `Output`", ); - err.span_suggestion_verbose( - base.span.shrink_to_hi(), - "consider `await`ing on the `Future` and access the field of its `Output`", - ".await", - Applicability::MaybeIncorrect, - ); + match self.tcx.coroutine_kind(self.body_id) { + Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => { + err.span_suggestion_verbose( + base.span.shrink_to_hi(), + "consider `await`ing on the `Future` to access the field", + ".await", + Applicability::MaybeIncorrect, + ); + } + _ => { + let mut span: MultiSpan = base.span.into(); + span.push_span_label(self.tcx.def_span(self.body_id), "this is not `async`"); + err.span_note( + span, + "this implements `Future` and its output type has the field, \ + but the future cannot be awaited in a synchronous function", + ); + } + } } fn ban_nonexisting_field( diff --git a/tests/ui/async-await/field-in-sync.rs b/tests/ui/async-await/field-in-sync.rs new file mode 100644 index 0000000000000..586980c6e2be6 --- /dev/null +++ b/tests/ui/async-await/field-in-sync.rs @@ -0,0 +1,13 @@ +//@ edition: 2021 + +struct S { + field: (), +} + +async fn foo() -> S { todo!() } + +fn main() -> Result<(), ()> { + foo().field; + //~^ ERROR no field `field` on type `impl Future` + Ok(()) +} diff --git a/tests/ui/async-await/field-in-sync.stderr b/tests/ui/async-await/field-in-sync.stderr new file mode 100644 index 0000000000000..7be30339c275b --- /dev/null +++ b/tests/ui/async-await/field-in-sync.stderr @@ -0,0 +1,17 @@ +error[E0609]: no field `field` on type `impl Future` + --> $DIR/field-in-sync.rs:10:11 + | +LL | foo().field; + | ^^^^^ field not available in `impl Future`, but it is available in its `Output` + | +note: this implements `Future` and its output type has the field, but the future cannot be awaited in a synchronous function + --> $DIR/field-in-sync.rs:10:5 + | +LL | fn main() -> Result<(), ()> { + | --------------------------- this is not `async` +LL | foo().field; + | ^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/async-await/issue-61076.stderr b/tests/ui/async-await/issue-61076.stderr index 44de282988baa..b8478c8d1388d 100644 --- a/tests/ui/async-await/issue-61076.stderr +++ b/tests/ui/async-await/issue-61076.stderr @@ -28,7 +28,7 @@ error[E0609]: no field `0` on type `impl Future` LL | let _: i32 = tuple().0; | ^ field not available in `impl Future`, but it is available in its `Output` | -help: consider `await`ing on the `Future` and access the field of its `Output` +help: consider `await`ing on the `Future` to access the field | LL | let _: i32 = tuple().await.0; | ++++++ @@ -39,7 +39,7 @@ error[E0609]: no field `a` on type `impl Future` LL | let _: i32 = struct_().a; | ^ field not available in `impl Future`, but it is available in its `Output` | -help: consider `await`ing on the `Future` and access the field of its `Output` +help: consider `await`ing on the `Future` to access the field | LL | let _: i32 = struct_().await.a; | ++++++