about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-10-12 06:11:11 -0400
committerMichael Goulet <michael@errs.io>2024-10-12 06:14:46 -0400
commitc8b71ef3dd83f1d6b99d128ff2fc3b99c9ce28ab (patch)
treedb125fe4676f0e15ef7cf898002d5908d18d14e8
parent5e8820caaa91f3d7740303e9e7047fbfb82281ce (diff)
downloadrust-c8b71ef3dd83f1d6b99d128ff2fc3b99c9ce28ab.tar.gz
rust-c8b71ef3dd83f1d6b99d128ff2fc3b99c9ce28ab.zip
Also note for fields
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs28
-rw-r--r--tests/ui/async-await/field-in-sync.rs13
-rw-r--r--tests/ui/async-await/field-in-sync.stderr17
-rw-r--r--tests/ui/async-await/issue-61076.stderr4
4 files changed, 53 insertions, 9 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index b310398a0f1..bd35a3a8e88 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 00000000000..586980c6e2b
--- /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<Output = S>`
+    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 00000000000..7be30339c27
--- /dev/null
+++ b/tests/ui/async-await/field-in-sync.stderr
@@ -0,0 +1,17 @@
+error[E0609]: no field `field` on type `impl Future<Output = S>`
+  --> $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 44de282988b..b8478c8d138 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<Output = Tuple>`
 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<Output = Struct>`
 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;
    |                           ++++++