Skip to content

Commit 274c3de

Browse files
authored
Rollup merge of rust-lang#62152 - doctorn:async_let_ice, r=cramertj
Don't ICE on item in `.await` expression The code for lowering a `.await` expression missed that item IDs may already have been assigned for items inside of an `async` block, or for closures. This change means we no longer exit early after finding a `.await` in a block that isn't `async` and instead just emit the error. This avoids an ICE generated due to item IDs not being densely generated. (The `YieldSource` of the generated `yield` expression is used to avoid errors generated about having `yield` expressions outside of generator literals.) r? @cramertj Resolves rust-lang#62009 and resolves rust-lang#61685
2 parents 4aa3e27 + 5cb841d commit 274c3de

File tree

7 files changed

+89
-9
lines changed

7 files changed

+89
-9
lines changed

src/librustc/hir/lowering.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5795,7 +5795,6 @@ impl<'a> LoweringContext<'a> {
57955795
err.span_label(item_sp, "this is not `async`");
57965796
}
57975797
err.emit();
5798-
return hir::ExprKind::Err;
57995798
}
58005799
}
58015800
let span = self.mark_span_with_reason(

src/librustc/hir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,7 @@ pub enum GeneratorMovability {
17131713
}
17141714

17151715
/// The yield kind that caused an `ExprKind::Yield`.
1716-
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
1716+
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
17171717
pub enum YieldSource {
17181718
/// An `<expr>.await`.
17191719
Await,

src/librustc_typeck/check/expr.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
295295
ExprKind::Index(ref base, ref idx) => {
296296
self.check_expr_index(base, idx, needs, expr)
297297
}
298-
ExprKind::Yield(ref value, _) => {
299-
self.check_expr_yield(value, expr)
298+
ExprKind::Yield(ref value, ref src) => {
299+
self.check_expr_yield(value, expr, src)
300300
}
301301
hir::ExprKind::Err => {
302302
tcx.types.err
@@ -1541,12 +1541,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15411541
}
15421542
}
15431543

1544-
fn check_expr_yield(&self, value: &'tcx hir::Expr, expr: &'tcx hir::Expr) -> Ty<'tcx> {
1544+
fn check_expr_yield(
1545+
&self,
1546+
value: &'tcx hir::Expr,
1547+
expr: &'tcx hir::Expr,
1548+
src: &'tcx hir::YieldSource
1549+
) -> Ty<'tcx> {
15451550
match self.yield_ty {
15461551
Some(ty) => {
15471552
self.check_expr_coercable_to_type(&value, ty);
15481553
}
1549-
None => {
1554+
// Given that this `yield` expression was generated as a result of lowering a `.await`,
1555+
// we know that the yield type must be `()`; however, the context won't contain this
1556+
// information. Hence, we check the source of the yield expression here and check its
1557+
// value's type against `()` (this check should always hold).
1558+
None if src == &hir::YieldSource::Await => {
1559+
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
1560+
}
1561+
_ => {
15501562
struct_span_err!(self.tcx.sess, expr.span, E0627,
15511563
"yield statement outside of generator literal").emit();
15521564
}

src/test/ui/async-await/issues/issue-51719.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
async fn foo() {}
88

99
fn make_generator() {
10-
let _gen = || foo.await; //~ ERROR `await` is only allowed inside `async` functions and blocks
10+
let _gen = || foo().await;
11+
//~^ ERROR `await` is only allowed inside `async` functions and blocks
1112
}
1213

1314
fn main() {}

src/test/ui/async-await/issues/issue-51719.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/issue-51719.rs:10:19
33
|
4-
LL | let _gen = || foo.await;
5-
| -- ^^^^^^^^^ only allowed inside `async` functions and blocks
4+
LL | let _gen = || foo().await;
5+
| -- ^^^^^^^^^^^ only allowed inside `async` functions and blocks
66
| |
77
| this is not `async`
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// edition:2018
2+
3+
#![feature(async_await)]
4+
5+
async fn print_dur() {}
6+
7+
fn main() {
8+
async { let (); }.await;
9+
//~^ ERROR `await` is only allowed inside `async` functions and blocks
10+
async {
11+
//~^ ERROR `await` is only allowed inside `async` functions and blocks
12+
let task1 = print_dur().await;
13+
}.await;
14+
(async || 2333)().await;
15+
//~^ ERROR `await` is only allowed inside `async` functions and blocks
16+
(|_| 2333).await;
17+
//~^ ERROR `await` is only allowed inside `async` functions and blocks
18+
//~^^ ERROR
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error[E0728]: `await` is only allowed inside `async` functions and blocks
2+
--> $DIR/issue-62009.rs:8:5
3+
|
4+
LL | fn main() {
5+
| ---- this is not `async`
6+
LL | async { let (); }.await;
7+
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
8+
9+
error[E0728]: `await` is only allowed inside `async` functions and blocks
10+
--> $DIR/issue-62009.rs:10:5
11+
|
12+
LL | fn main() {
13+
| ---- this is not `async`
14+
...
15+
LL | / async {
16+
LL | |
17+
LL | | let task1 = print_dur().await;
18+
LL | | }.await;
19+
| |___________^ only allowed inside `async` functions and blocks
20+
21+
error[E0728]: `await` is only allowed inside `async` functions and blocks
22+
--> $DIR/issue-62009.rs:14:5
23+
|
24+
LL | fn main() {
25+
| ---- this is not `async`
26+
...
27+
LL | (async || 2333)().await;
28+
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
29+
30+
error[E0728]: `await` is only allowed inside `async` functions and blocks
31+
--> $DIR/issue-62009.rs:16:5
32+
|
33+
LL | fn main() {
34+
| ---- this is not `async`
35+
...
36+
LL | (|_| 2333).await;
37+
| ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
38+
39+
error[E0277]: the trait bound `[closure@$DIR/issue-62009.rs:16:5: 16:15]: std::future::Future` is not satisfied
40+
--> $DIR/issue-62009.rs:16:5
41+
|
42+
LL | (|_| 2333).await;
43+
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009.rs:16:5: 16:15]`
44+
|
45+
= note: required by `std::future::poll_with_tls_context`
46+
47+
error: aborting due to 5 previous errors
48+
49+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)