Skip to content

Commit 4496f23

Browse files
authored
Rollup merge of #135492 - metamuffin:bug-invalid-await-suggest, r=compiler-errors
Add missing check for async body when suggesting await on futures. Currently the compiler suggests adding `.await` to resolve some type conflicts without checking if the conflict happens in an async context. This can lead to the compiler suggesting `.await` in function signatures where it is invalid. Example: ```rs trait A { fn a() -> impl Future<Output = ()>; } struct B; impl A for B { fn a() -> impl Future<Output = impl Future<Output = ()>> { async { async { () } } } } ``` ``` error[E0271]: expected `impl Future<Output = impl Future<Output = ()>>` to be a future that resolves to `()`, but it resolves to `impl Future<Output = ()>` --> bug.rs:6:15 | 6 | fn a() -> impl Future<Output = impl Future<Output = ()>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found future | note: calling an async function returns a future --> bug.rs:6:15 | 6 | fn a() -> impl Future<Output = impl Future<Output = ()>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `A::{synthetic#0}` --> bug.rs:2:27 | 2 | fn a() -> impl Future<Output = ()>; | ^^^^^^^^^^^ required by this bound in `A::{synthetic#0}` help: consider `await`ing on the `Future` | 6 | fn a() -> impl Future<Output = impl Future<Output = ()>>.await { | ++++++ ``` The documentation of suggest_await_on_expect_found (`compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs:156`) even mentions such a check but does not actually implement it. This PR adds that check to ensure `.await` is only suggested within async blocks. There were 3 unit tests whose expected output needed to be changed because they had the suggestion outside of async. One of them (`tests/ui/async-await/dont-suggest-missing-await.rs`) actually tests that exact problem but expects it to be present. Thanks to `@llenck` for initially noticing the bug and helping with fixing it
2 parents 08d5b23 + ab2c8ff commit 4496f23

File tree

4 files changed

+12
-19
lines changed

4 files changed

+12
-19
lines changed

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

+12
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
167167
exp_span, exp_found.expected, exp_found.found,
168168
);
169169

170+
match self.tcx.coroutine_kind(cause.body_id) {
171+
Some(hir::CoroutineKind::Desugared(
172+
hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen,
173+
_,
174+
)) => (),
175+
None
176+
| Some(
177+
hir::CoroutineKind::Coroutine(_)
178+
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _),
179+
) => return,
180+
}
181+
170182
if let ObligationCauseCode::CompareImplItem { .. } = cause.code() {
171183
return;
172184
}

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

-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ LL | fun(one(), two());
3030
| | expected all arguments to be this future type because they need to match the type of this parameter
3131
| arguments to this function are incorrect
3232
|
33-
= help: consider `await`ing on both `Future`s
3433
= note: distinct uses of `impl Trait` result in different opaque types
3534
note: function defined here
3635
--> $DIR/coroutine-desc.rs:7:4

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

-9
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,11 @@ LL | take_u32(x)
66
| |
77
| arguments to this function are incorrect
88
|
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-
| ^
149
note: function defined here
1510
--> $DIR/dont-suggest-missing-await.rs:5:4
1611
|
1712
LL | fn take_u32(x: u32) {}
1813
| ^^^^^^^^ ------
19-
help: consider `await`ing on the `Future`
20-
|
21-
LL | take_u32(x.await)
22-
| ++++++
2314

2415
error: aborting due to 1 previous error
2516

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

-9
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,11 @@ LL | convert_result(foo())
1414
| |
1515
| arguments to this function are incorrect
1616
|
17-
note: calling an async function returns a future
18-
--> $DIR/issue-102605.rs:13:20
19-
|
20-
LL | convert_result(foo())
21-
| ^^^^^
2217
note: function defined here
2318
--> $DIR/issue-102605.rs:7:4
2419
|
2520
LL | fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
2621
| ^^^^^^^^^^^^^^ ---------------
27-
help: consider `await`ing on the `Future`
28-
|
29-
LL | convert_result(foo().await)
30-
| ++++++
3122
help: try wrapping the expression in `Err`
3223
|
3324
LL | convert_result(Err(foo()))

0 commit comments

Comments
 (0)