Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improve the suggestion on future not awaited #107902

Merged
merged 1 commit into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1783,14 +1783,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}))
{
diag.note_expected_found_extra(
&expected_label,
expected,
&found_label,
found,
&sort_string(values.expected, exp_p),
&sort_string(values.found, found_p),
);
if let Some(ExpectedFound { found: found_ty, .. }) = exp_found {
// `Future` is a special opaque type that the compiler
// will try to hide in some case such as `async fn`, so
// to make an error more use friendly we will
// avoid to suggest a mismatch type with a
// type that the user usually are not usign
// directly such as `impl Future<Output = u8>`.
if !self.tcx.ty_is_opaque_future(found_ty) {
diag.note_expected_found_extra(
&expected_label,
expected,
&found_label,
found,
&sort_string(values.expected, exp_p),
&sort_string(values.found, found_p),
);
}
}
}
}
_ => {
Expand Down Expand Up @@ -2854,6 +2864,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
pub enum TyCategory {
Closure,
Opaque,
OpaqueFuture,
Generator(hir::GeneratorKind),
Foreign,
}
Expand All @@ -2863,6 +2874,7 @@ impl TyCategory {
match self {
Self::Closure => "closure",
Self::Opaque => "opaque type",
Self::OpaqueFuture => "future",
Self::Generator(gk) => gk.descr(),
Self::Foreign => "foreign type",
}
Expand All @@ -2871,7 +2883,11 @@ impl TyCategory {
pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
match *ty.kind() {
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => Some((Self::Opaque, def_id)),
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
let kind =
if tcx.ty_is_opaque_future(ty) { Self::OpaqueFuture } else { Self::Opaque };
Some((kind, def_id))
}
ty::Generator(def_id, ..) => {
Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
}
Expand Down
31 changes: 13 additions & 18 deletions compiler/rustc_infer/src/infer/error_reporting/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,31 +238,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
},
(_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
diag.span_suggestion_verbose(
exp_span.shrink_to_hi(),
"consider `await`ing on the `Future`",
".await",
Applicability::MaybeIncorrect,
);
self.suggest_await_on_future(diag, exp_span);
diag.span_note(exp_span, "calling an async function returns a future");
}
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
{
ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
diag.span_suggestion_verbose(
then_span.shrink_to_hi(),
"consider `await`ing on the `Future`",
".await",
Applicability::MaybeIncorrect,
);
self.suggest_await_on_future(diag, then_span.shrink_to_hi());
}
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id);
diag.span_suggestion_verbose(
then_span.shrink_to_hi(),
"consider `await`ing on the `Future`",
".await",
Applicability::MaybeIncorrect,
);
self.suggest_await_on_future(diag, then_span.shrink_to_hi());
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
ref prior_arms,
Expand All @@ -283,6 +269,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}

pub fn suggest_await_on_future(&self, diag: &mut Diagnostic, sp: Span) {
diag.span_suggestion_verbose(
sp.shrink_to_hi(),
"consider `await`ing on the `Future`",
".await",
Applicability::MaybeIncorrect,
);
}

pub(super) fn suggest_accessing_field_where_appropriate(
&self,
cause: &ObligationCause<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ impl<'tcx> Ty<'tcx> {
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
ty::Alias(ty::Projection, _) => "associated type".into(),
ty::Param(p) => format!("type parameter `{p}`").into(),
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
ty::Alias(ty::Opaque, ..) => if tcx.ty_is_opaque_future(self) { "future".into() } else { "opaque type".into() },
ty::Error(_) => "type error".into(),
_ => {
let width = tcx.sess.diagnostic_width();
Expand Down
9 changes: 6 additions & 3 deletions tests/ui/async-await/dont-suggest-missing-await.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ error[E0308]: mismatched types
--> $DIR/dont-suggest-missing-await.rs:14:18
|
LL | take_u32(x)
| -------- ^ expected `u32`, found opaque type
| -------- ^ expected `u32`, found future
| |
| arguments to this function are incorrect
|
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
note: calling an async function returns a future
--> $DIR/dont-suggest-missing-await.rs:14:18
|
LL | take_u32(x)
| ^
note: function defined here
--> $DIR/dont-suggest-missing-await.rs:5:4
|
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/async-await/generator-desc.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ error[E0308]: mismatched types
--> $DIR/generator-desc.rs:12:16
|
LL | fun(one(), two());
| --- ^^^^^ expected opaque type, found a different opaque type
| --- ^^^^^ expected future, found a different future
| |
| arguments to this function are incorrect
|
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this message should also be specialized for futures.

Suggested change
= note: distinct uses of `impl Trait` result in different opaque types
= note: each `async fn` produces a future that is a unique type

That message sucks but something like that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you, but this suggestion looks unrelated to this PR? maybe the right position is a followup PR?

note: function defined here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0053]: method `foo` has an incompatible type for trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
|
LL | async fn foo(&self) -> i32 {
| ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found opaque type
| ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found future
|
note: type in trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/issue-61076.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ async fn match_() {
match tuple() { //~ HELP consider `await`ing on the `Future`
//~^ NOTE this expression has type `impl Future<Output = Tuple>`
Tuple(_) => {} //~ ERROR mismatched types
//~^ NOTE expected opaque type, found `Tuple`
//~^ NOTE expected future, found `Tuple`
//~| NOTE expected opaque type `impl Future<Output = Tuple>`
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/issue-61076.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ LL | match tuple() {
| ------- this expression has type `impl Future<Output = Tuple>`
LL |
LL | Tuple(_) => {}
| ^^^^^^^^ expected opaque type, found `Tuple`
| ^^^^^^^^ expected future, found `Tuple`
|
= note: expected opaque type `impl Future<Output = Tuple>`
found struct `Tuple`
Expand Down
12 changes: 3 additions & 9 deletions tests/ui/async-await/issue-98634.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Futu
--> $DIR/issue-98634.rs:45:23
|
LL | StructAsync { callback }.await;
| ^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
| ^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
|
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
--> $DIR/issue-98634.rs:9:35
|
Expand All @@ -16,10 +14,8 @@ error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Futu
--> $DIR/issue-98634.rs:45:9
|
LL | StructAsync { callback }.await;
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
|
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
--> $DIR/issue-98634.rs:9:35
|
Expand All @@ -30,10 +26,8 @@ error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Futu
--> $DIR/issue-98634.rs:45:33
|
LL | StructAsync { callback }.await;
| ^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
| ^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
|
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
--> $DIR/issue-98634.rs:9:35
|
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/async-await/issues/issue-102206.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ error[E0308]: mismatched types
LL | std::mem::size_of_val(foo());
| --------------------- ^^^^^
| | |
| | expected `&_`, found opaque type
| | expected `&_`, found future
| | help: consider borrowing here: `&foo()`
| arguments to this function are incorrect
|
= note: expected reference `&_`
found opaque type `impl Future<Output = ()>`
note: function defined here
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL

Expand Down
9 changes: 6 additions & 3 deletions tests/ui/async-await/suggest-missing-await-closure.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ error[E0308]: mismatched types
--> $DIR/suggest-missing-await-closure.rs:16:18
|
LL | take_u32(x)
| -------- ^ expected `u32`, found opaque type
| -------- ^ expected `u32`, found future
| |
| arguments to this function are incorrect
|
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
note: calling an async function returns a future
--> $DIR/suggest-missing-await-closure.rs:16:18
|
LL | take_u32(x)
| ^
note: function defined here
--> $DIR/suggest-missing-await-closure.rs:6:4
|
Expand Down
28 changes: 17 additions & 11 deletions tests/ui/async-await/suggest-missing-await.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:12:14
|
LL | take_u32(x)
| -------- ^ expected `u32`, found opaque type
| -------- ^ expected `u32`, found future
| |
| arguments to this function are incorrect
|
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
note: calling an async function returns a future
--> $DIR/suggest-missing-await.rs:12:14
|
LL | take_u32(x)
| ^
note: function defined here
--> $DIR/suggest-missing-await.rs:3:4
|
Expand All @@ -22,10 +25,13 @@ error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:22:5
|
LL | dummy()
| ^^^^^^^ expected `()`, found opaque type
| ^^^^^^^ expected `()`, found future
|
= note: expected unit type `()`
found opaque type `impl Future<Output = ()>`
note: calling an async function returns a future
--> $DIR/suggest-missing-await.rs:22:5
|
LL | dummy()
| ^^^^^^^
help: consider `await`ing on the `Future`
|
LL | dummy().await
Expand All @@ -45,7 +51,7 @@ LL | | dummy()
LL | |
LL | | } else {
LL | | dummy().await
| | ^^^^^^^^^^^^^ expected opaque type, found `()`
| | ^^^^^^^^^^^^^ expected future, found `()`
LL | |
LL | | };
| |_____- `if` and `else` have incompatible types
Expand All @@ -67,7 +73,7 @@ LL | | 0 => dummy(),
LL | | 1 => dummy(),
| | ------- this is found to be of type `impl Future<Output = ()>`
LL | | 2 => dummy().await,
| | ^^^^^^^^^^^^^ expected opaque type, found `()`
| | ^^^^^^^^^^^^^ expected future, found `()`
LL | |
LL | | };
| |_____- `match` arms have incompatible types
Expand All @@ -86,7 +92,7 @@ error[E0308]: mismatched types
LL | let _x = match dummy() {
| ------- this expression has type `impl Future<Output = ()>`
LL | () => {}
| ^^ expected opaque type, found `()`
| ^^ expected future, found `()`
|
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
Expand All @@ -102,7 +108,7 @@ LL | match dummy_result() {
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
...
LL | Ok(_) => {}
| ^^^^^ expected opaque type, found `Result<_, _>`
| ^^^^^ expected future, found `Result<_, _>`
|
= note: expected opaque type `impl Future<Output = Result<(), ()>>`
found enum `Result<_, _>`
Expand All @@ -118,7 +124,7 @@ LL | match dummy_result() {
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
...
LL | Err(_) => {}
| ^^^^^^ expected opaque type, found `Result<_, _>`
| ^^^^^^ expected future, found `Result<_, _>`
|
= note: expected opaque type `impl Future<Output = Result<(), ()>>`
found enum `Result<_, _>`
Expand Down
9 changes: 6 additions & 3 deletions tests/ui/impl-trait/issue-102605.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ error[E0308]: mismatched types
--> $DIR/issue-102605.rs:13:20
|
LL | convert_result(foo())
| -------------- ^^^^^ expected `Result<(), _>`, found opaque type
| -------------- ^^^^^ expected `Result<(), _>`, found future
| |
| arguments to this function are incorrect
|
= note: expected enum `Result<(), _>`
found opaque type `impl Future<Output = Result<(), String>>`
note: calling an async function returns a future
--> $DIR/issue-102605.rs:13:20
|
LL | convert_result(foo())
| ^^^^^
note: function defined here
--> $DIR/issue-102605.rs:7:4
|
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/impl-trait/issue-99914.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0308]: mismatched types
--> $DIR/issue-99914.rs:9:27
|
LL | t.and_then(|t| -> _ { bar(t) });
| ^^^^^^ expected `Result<_, Error>`, found opaque type
| ^^^^^^ expected `Result<_, Error>`, found future
|
= note: expected enum `Result<_, Error>`
found opaque type `impl Future<Output = ()>`
help: try wrapping the expression in `Ok`
|
LL | t.and_then(|t| -> _ { Ok(bar(t)) });
Expand Down
11 changes: 5 additions & 6 deletions tests/ui/suggestions/if-then-neeing-semi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ async fn async_extra_semicolon_same() {
//~^ HELP consider removing this semicolon
} else {
async_dummy() //~ ERROR `if` and `else` have incompatible types
//~^ NOTE expected `()`, found opaque type
//~| NOTE expected unit type `()`
//~^ NOTE expected `()`, found future
//~| NOTE calling an async function returns a future
//~| HELP consider `await`ing on the `Future`
};
}
Expand All @@ -39,8 +39,8 @@ async fn async_extra_semicolon_different() {
//~^ HELP consider removing this semicolon
} else {
async_dummy2() //~ ERROR `if` and `else` have incompatible types
//~^ NOTE expected `()`, found opaque type
//~| NOTE expected unit type `()`
//~^ NOTE expected `()`, found future
//~| NOTE calling an async function returns a future
//~| HELP consider `await`ing on the `Future`
};
}
Expand All @@ -52,8 +52,7 @@ async fn async_different_futures() {
//~| HELP consider `await`ing on both `Future`s
} else {
async_dummy2() //~ ERROR `if` and `else` have incompatible types
//~^ NOTE expected opaque type, found a different opaque type
//~| NOTE expected opaque type `impl Future<Output = ()>`
//~^ NOTE expected future, found a different future
//~| NOTE distinct uses of `impl Trait` result in different opaque types
};
}
Expand Down
Loading