Add a note for ? on future in sync function

This commit is contained in:
Michael Goulet 2024-10-11 10:59:09 -04:00
parent fb20e4d3b9
commit 5e8820caaa
3 changed files with 84 additions and 45 deletions
compiler/rustc_trait_selection/src/error_reporting/traits
tests/ui/async-await

View file

@ -3594,9 +3594,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
span: Span,
) {
if let Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) =
self.tcx.coroutine_kind(obligation.cause.body_id)
{
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
@ -3634,6 +3631,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
&& snippet.ends_with('?')
{
match self.tcx.coroutine_kind(obligation.cause.body_id) {
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
err.span_suggestion_verbose(
span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
"consider `await`ing on the `Future`",
@ -3641,6 +3640,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
Applicability::MaybeIncorrect,
);
}
_ => {
let mut span: MultiSpan = span.with_lo(span.hi() - BytePos(1)).into();
span.push_span_label(
self.tcx.def_span(obligation.cause.body_id),
"this is not `async`",
);
err.span_note(
span,
"this implements `Future` and its output type supports \
`?`, but the future cannot be awaited in a synchronous function",
);
}
}
}
}

View file

@ -0,0 +1,9 @@
//@ edition: 2021
async fn foo() -> Result<(), ()> { todo!() }
fn main() -> Result<(), ()> {
foo()?;
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
Ok(())
}

View file

@ -0,0 +1,18 @@
error[E0277]: the `?` operator can only be applied to values that implement `Try`
--> $DIR/try-in-sync.rs:6:5
|
LL | foo()?;
| ^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), ()>>`
|
= help: the trait `Try` is not implemented for `impl Future<Output = Result<(), ()>>`
note: this implements `Future` and its output type supports `?`, but the future cannot be awaited in a synchronous function
--> $DIR/try-in-sync.rs:6:10
|
LL | fn main() -> Result<(), ()> {
| --------------------------- this is not `async`
LL | foo()?;
| ^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.