Skip to content

Commit 73b022b

Browse files
authored
Rollup merge of #107902 - vincenzopalazzo:macros/async_fn_suggestion, r=compiler-errors
fix: improve the suggestion on future not awaited Considering the following code ```rust fn foo() -> u8 { async fn async_fn() -> u8 { 22 } async_fn() } fn main() {} ``` the error generated before this commit from the compiler is ``` ➜ rust git:(macros/async_fn_suggestion) ✗ rustc test.rs --edition 2021 error[E0308]: mismatched types --> test.rs:4:5 | 1 | fn foo() -> u8 { | -- expected `u8` because of return type ... 4 | async_fn() | ^^^^^^^^^^ expected `u8`, found opaque type | = note: expected type `u8` found opaque type `impl Future<Output = u8>` help: consider `await`ing on the `Future` | 4 | async_fn().await | ++++++ error: aborting due to previous error ``` In this case the error is nor perfect, and can confuse the user that do not know that the opaque type is the future. So this commit will propose (and conclude the work start in #80658) to change the string `opaque type` to `future` when applicable and also remove the Expected vs Received note by adding a more specific one regarding the async function that return a future type. So the new error emitted by the compiler is ``` error[E0308]: mismatched types --> test.rs:4:5 | 1 | fn foo() -> u8 { | -- expected `u8` because of return type ... 4 | async_fn() | ^^^^^^^^^^ expected `u8`, found future | note: calling an async function returns a future --> test.rs:4:5 | 4 | async_fn() | ^^^^^^^^^^ help: consider `await`ing on the `Future` | 4 | async_fn().await | ++++++ error: aborting due to previous error ``` Fixes #80658 It remains to rework the case described in the following issue #107899 but I think this deserves its own PR after we discuss a little bit how to handle these kinds of cases. r? `@eholk` `@rustbot` label +I-async-nominated Signed-off-by: Vincenzo Palazzo <[email protected]>
2 parents a3c9eed + 2bdc9a0 commit 73b022b

22 files changed

+132
-116
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -1783,14 +1783,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
17831783
}
17841784
}))
17851785
{
1786-
diag.note_expected_found_extra(
1787-
&expected_label,
1788-
expected,
1789-
&found_label,
1790-
found,
1791-
&sort_string(values.expected, exp_p),
1792-
&sort_string(values.found, found_p),
1793-
);
1786+
if let Some(ExpectedFound { found: found_ty, .. }) = exp_found {
1787+
// `Future` is a special opaque type that the compiler
1788+
// will try to hide in some case such as `async fn`, so
1789+
// to make an error more use friendly we will
1790+
// avoid to suggest a mismatch type with a
1791+
// type that the user usually are not usign
1792+
// directly such as `impl Future<Output = u8>`.
1793+
if !self.tcx.ty_is_opaque_future(found_ty) {
1794+
diag.note_expected_found_extra(
1795+
&expected_label,
1796+
expected,
1797+
&found_label,
1798+
found,
1799+
&sort_string(values.expected, exp_p),
1800+
&sort_string(values.found, found_p),
1801+
);
1802+
}
1803+
}
17941804
}
17951805
}
17961806
_ => {
@@ -2854,6 +2864,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
28542864
pub enum TyCategory {
28552865
Closure,
28562866
Opaque,
2867+
OpaqueFuture,
28572868
Generator(hir::GeneratorKind),
28582869
Foreign,
28592870
}
@@ -2863,6 +2874,7 @@ impl TyCategory {
28632874
match self {
28642875
Self::Closure => "closure",
28652876
Self::Opaque => "opaque type",
2877+
Self::OpaqueFuture => "future",
28662878
Self::Generator(gk) => gk.descr(),
28672879
Self::Foreign => "foreign type",
28682880
}
@@ -2871,7 +2883,11 @@ impl TyCategory {
28712883
pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
28722884
match *ty.kind() {
28732885
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
2874-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => Some((Self::Opaque, def_id)),
2886+
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
2887+
let kind =
2888+
if tcx.ty_is_opaque_future(ty) { Self::OpaqueFuture } else { Self::Opaque };
2889+
Some((kind, def_id))
2890+
}
28752891
ty::Generator(def_id, ..) => {
28762892
Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
28772893
}

compiler/rustc_infer/src/infer/error_reporting/suggest.rs

+13-18
Original file line numberDiff line numberDiff line change
@@ -238,31 +238,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
238238
}
239239
},
240240
(_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
241-
diag.span_suggestion_verbose(
242-
exp_span.shrink_to_hi(),
243-
"consider `await`ing on the `Future`",
244-
".await",
245-
Applicability::MaybeIncorrect,
246-
);
241+
self.suggest_await_on_future(diag, exp_span);
242+
diag.span_note(exp_span, "calling an async function returns a future");
247243
}
248244
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
249245
{
250246
ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
251-
diag.span_suggestion_verbose(
252-
then_span.shrink_to_hi(),
253-
"consider `await`ing on the `Future`",
254-
".await",
255-
Applicability::MaybeIncorrect,
256-
);
247+
self.suggest_await_on_future(diag, then_span.shrink_to_hi());
257248
}
258249
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
259250
let then_span = self.find_block_span_from_hir_id(*then_id);
260-
diag.span_suggestion_verbose(
261-
then_span.shrink_to_hi(),
262-
"consider `await`ing on the `Future`",
263-
".await",
264-
Applicability::MaybeIncorrect,
265-
);
251+
self.suggest_await_on_future(diag, then_span.shrink_to_hi());
266252
}
267253
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
268254
ref prior_arms,
@@ -283,6 +269,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
283269
}
284270
}
285271

272+
pub fn suggest_await_on_future(&self, diag: &mut Diagnostic, sp: Span) {
273+
diag.span_suggestion_verbose(
274+
sp.shrink_to_hi(),
275+
"consider `await`ing on the `Future`",
276+
".await",
277+
Applicability::MaybeIncorrect,
278+
);
279+
}
280+
286281
pub(super) fn suggest_accessing_field_where_appropriate(
287282
&self,
288283
cause: &ObligationCause<'tcx>,

compiler/rustc_middle/src/ty/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ impl<'tcx> Ty<'tcx> {
271271
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
272272
ty::Alias(ty::Projection, _) => "associated type".into(),
273273
ty::Param(p) => format!("type parameter `{p}`").into(),
274-
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
274+
ty::Alias(ty::Opaque, ..) => if tcx.ty_is_opaque_future(self) { "future".into() } else { "opaque type".into() },
275275
ty::Error(_) => "type error".into(),
276276
_ => {
277277
let width = tcx.sess.diagnostic_width();

tests/ui/async-await/dont-suggest-missing-await.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ error[E0308]: mismatched types
22
--> $DIR/dont-suggest-missing-await.rs:14:18
33
|
44
LL | take_u32(x)
5-
| -------- ^ expected `u32`, found opaque type
5+
| -------- ^ expected `u32`, found future
66
| |
77
| arguments to this function are incorrect
88
|
9-
= note: expected type `u32`
10-
found opaque type `impl Future<Output = u32>`
9+
note: calling an async function returns a future
10+
--> $DIR/dont-suggest-missing-await.rs:14:18
11+
|
12+
LL | take_u32(x)
13+
| ^
1114
note: function defined here
1215
--> $DIR/dont-suggest-missing-await.rs:5:4
1316
|

tests/ui/async-await/generator-desc.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ error[E0308]: mismatched types
1717
--> $DIR/generator-desc.rs:12:16
1818
|
1919
LL | fun(one(), two());
20-
| --- ^^^^^ expected opaque type, found a different opaque type
20+
| --- ^^^^^ expected future, found a different future
2121
| |
2222
| arguments to this function are incorrect
2323
|
24-
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
25-
found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
2624
= help: consider `await`ing on both `Future`s
2725
= note: distinct uses of `impl Trait` result in different opaque types
2826
note: function defined here

tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0053]: method `foo` has an incompatible type for trait
22
--> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
33
|
44
LL | async fn foo(&self) -> i32 {
5-
| ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found opaque type
5+
| ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found future
66
|
77
note: type in trait
88
--> $DIR/async-example-desugared-boxed-in-trait.rs:11:22

tests/ui/async-await/issue-61076.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async fn match_() {
8686
match tuple() { //~ HELP consider `await`ing on the `Future`
8787
//~^ NOTE this expression has type `impl Future<Output = Tuple>`
8888
Tuple(_) => {} //~ ERROR mismatched types
89-
//~^ NOTE expected opaque type, found `Tuple`
89+
//~^ NOTE expected future, found `Tuple`
9090
//~| NOTE expected opaque type `impl Future<Output = Tuple>`
9191
}
9292
}

tests/ui/async-await/issue-61076.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ LL | match tuple() {
6262
| ------- this expression has type `impl Future<Output = Tuple>`
6363
LL |
6464
LL | Tuple(_) => {}
65-
| ^^^^^^^^ expected opaque type, found `Tuple`
65+
| ^^^^^^^^ expected future, found `Tuple`
6666
|
6767
= note: expected opaque type `impl Future<Output = Tuple>`
6868
found struct `Tuple`

tests/ui/async-await/issue-98634.stderr

+3-9
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Futu
22
--> $DIR/issue-98634.rs:45:23
33
|
44
LL | StructAsync { callback }.await;
5-
| ^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
5+
| ^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
66
|
7-
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
8-
found opaque type `impl Future<Output = ()>`
97
note: required by a bound in `StructAsync`
108
--> $DIR/issue-98634.rs:9:35
119
|
@@ -16,10 +14,8 @@ error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Futu
1614
--> $DIR/issue-98634.rs:45:9
1715
|
1816
LL | StructAsync { callback }.await;
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
2018
|
21-
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
22-
found opaque type `impl Future<Output = ()>`
2319
note: required by a bound in `StructAsync`
2420
--> $DIR/issue-98634.rs:9:35
2521
|
@@ -30,10 +26,8 @@ error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Futu
3026
--> $DIR/issue-98634.rs:45:33
3127
|
3228
LL | StructAsync { callback }.await;
33-
| ^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found opaque type
29+
| ^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
3430
|
35-
= note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
36-
found opaque type `impl Future<Output = ()>`
3731
note: required by a bound in `StructAsync`
3832
--> $DIR/issue-98634.rs:9:35
3933
|

tests/ui/async-await/issues/issue-102206.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ error[E0308]: mismatched types
44
LL | std::mem::size_of_val(foo());
55
| --------------------- ^^^^^
66
| | |
7-
| | expected `&_`, found opaque type
7+
| | expected `&_`, found future
88
| | help: consider borrowing here: `&foo()`
99
| arguments to this function are incorrect
1010
|
11-
= note: expected reference `&_`
12-
found opaque type `impl Future<Output = ()>`
1311
note: function defined here
1412
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
1513

tests/ui/async-await/suggest-missing-await-closure.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ error[E0308]: mismatched types
22
--> $DIR/suggest-missing-await-closure.rs:16:18
33
|
44
LL | take_u32(x)
5-
| -------- ^ expected `u32`, found opaque type
5+
| -------- ^ expected `u32`, found future
66
| |
77
| arguments to this function are incorrect
88
|
9-
= note: expected type `u32`
10-
found opaque type `impl Future<Output = u32>`
9+
note: calling an async function returns a future
10+
--> $DIR/suggest-missing-await-closure.rs:16:18
11+
|
12+
LL | take_u32(x)
13+
| ^
1114
note: function defined here
1215
--> $DIR/suggest-missing-await-closure.rs:6:4
1316
|

tests/ui/async-await/suggest-missing-await.stderr

+17-11
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ error[E0308]: mismatched types
22
--> $DIR/suggest-missing-await.rs:12:14
33
|
44
LL | take_u32(x)
5-
| -------- ^ expected `u32`, found opaque type
5+
| -------- ^ expected `u32`, found future
66
| |
77
| arguments to this function are incorrect
88
|
9-
= note: expected type `u32`
10-
found opaque type `impl Future<Output = u32>`
9+
note: calling an async function returns a future
10+
--> $DIR/suggest-missing-await.rs:12:14
11+
|
12+
LL | take_u32(x)
13+
| ^
1114
note: function defined here
1215
--> $DIR/suggest-missing-await.rs:3:4
1316
|
@@ -22,10 +25,13 @@ error[E0308]: mismatched types
2225
--> $DIR/suggest-missing-await.rs:22:5
2326
|
2427
LL | dummy()
25-
| ^^^^^^^ expected `()`, found opaque type
28+
| ^^^^^^^ expected `()`, found future
2629
|
27-
= note: expected unit type `()`
28-
found opaque type `impl Future<Output = ()>`
30+
note: calling an async function returns a future
31+
--> $DIR/suggest-missing-await.rs:22:5
32+
|
33+
LL | dummy()
34+
| ^^^^^^^
2935
help: consider `await`ing on the `Future`
3036
|
3137
LL | dummy().await
@@ -45,7 +51,7 @@ LL | | dummy()
4551
LL | |
4652
LL | | } else {
4753
LL | | dummy().await
48-
| | ^^^^^^^^^^^^^ expected opaque type, found `()`
54+
| | ^^^^^^^^^^^^^ expected future, found `()`
4955
LL | |
5056
LL | | };
5157
| |_____- `if` and `else` have incompatible types
@@ -67,7 +73,7 @@ LL | | 0 => dummy(),
6773
LL | | 1 => dummy(),
6874
| | ------- this is found to be of type `impl Future<Output = ()>`
6975
LL | | 2 => dummy().await,
70-
| | ^^^^^^^^^^^^^ expected opaque type, found `()`
76+
| | ^^^^^^^^^^^^^ expected future, found `()`
7177
LL | |
7278
LL | | };
7379
| |_____- `match` arms have incompatible types
@@ -86,7 +92,7 @@ error[E0308]: mismatched types
8692
LL | let _x = match dummy() {
8793
| ------- this expression has type `impl Future<Output = ()>`
8894
LL | () => {}
89-
| ^^ expected opaque type, found `()`
95+
| ^^ expected future, found `()`
9096
|
9197
= note: expected opaque type `impl Future<Output = ()>`
9298
found unit type `()`
@@ -102,7 +108,7 @@ LL | match dummy_result() {
102108
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
103109
...
104110
LL | Ok(_) => {}
105-
| ^^^^^ expected opaque type, found `Result<_, _>`
111+
| ^^^^^ expected future, found `Result<_, _>`
106112
|
107113
= note: expected opaque type `impl Future<Output = Result<(), ()>>`
108114
found enum `Result<_, _>`
@@ -118,7 +124,7 @@ LL | match dummy_result() {
118124
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
119125
...
120126
LL | Err(_) => {}
121-
| ^^^^^^ expected opaque type, found `Result<_, _>`
127+
| ^^^^^^ expected future, found `Result<_, _>`
122128
|
123129
= note: expected opaque type `impl Future<Output = Result<(), ()>>`
124130
found enum `Result<_, _>`

tests/ui/impl-trait/issue-102605.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ error[E0308]: mismatched types
22
--> $DIR/issue-102605.rs:13:20
33
|
44
LL | convert_result(foo())
5-
| -------------- ^^^^^ expected `Result<(), _>`, found opaque type
5+
| -------------- ^^^^^ expected `Result<(), _>`, found future
66
| |
77
| arguments to this function are incorrect
88
|
9-
= note: expected enum `Result<(), _>`
10-
found opaque type `impl Future<Output = Result<(), String>>`
9+
note: calling an async function returns a future
10+
--> $DIR/issue-102605.rs:13:20
11+
|
12+
LL | convert_result(foo())
13+
| ^^^^^
1114
note: function defined here
1215
--> $DIR/issue-102605.rs:7:4
1316
|

tests/ui/impl-trait/issue-99914.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0308]: mismatched types
22
--> $DIR/issue-99914.rs:9:27
33
|
44
LL | t.and_then(|t| -> _ { bar(t) });
5-
| ^^^^^^ expected `Result<_, Error>`, found opaque type
5+
| ^^^^^^ expected `Result<_, Error>`, found future
66
|
7-
= note: expected enum `Result<_, Error>`
8-
found opaque type `impl Future<Output = ()>`
97
help: try wrapping the expression in `Ok`
108
|
119
LL | t.and_then(|t| -> _ { Ok(bar(t)) });

tests/ui/suggestions/if-then-neeing-semi.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ async fn async_extra_semicolon_same() {
2626
//~^ HELP consider removing this semicolon
2727
} else {
2828
async_dummy() //~ ERROR `if` and `else` have incompatible types
29-
//~^ NOTE expected `()`, found opaque type
30-
//~| NOTE expected unit type `()`
29+
//~^ NOTE expected `()`, found future
30+
//~| NOTE calling an async function returns a future
3131
//~| HELP consider `await`ing on the `Future`
3232
};
3333
}
@@ -39,8 +39,8 @@ async fn async_extra_semicolon_different() {
3939
//~^ HELP consider removing this semicolon
4040
} else {
4141
async_dummy2() //~ ERROR `if` and `else` have incompatible types
42-
//~^ NOTE expected `()`, found opaque type
43-
//~| NOTE expected unit type `()`
42+
//~^ NOTE expected `()`, found future
43+
//~| NOTE calling an async function returns a future
4444
//~| HELP consider `await`ing on the `Future`
4545
};
4646
}
@@ -52,8 +52,7 @@ async fn async_different_futures() {
5252
//~| HELP consider `await`ing on both `Future`s
5353
} else {
5454
async_dummy2() //~ ERROR `if` and `else` have incompatible types
55-
//~^ NOTE expected opaque type, found a different opaque type
56-
//~| NOTE expected opaque type `impl Future<Output = ()>`
55+
//~^ NOTE expected future, found a different future
5756
//~| NOTE distinct uses of `impl Trait` result in different opaque types
5857
};
5958
}

0 commit comments

Comments
 (0)