Skip to content

Commit

Permalink
Rollup merge of rust-lang#62152 - doctorn:async_let_ice, r=cramertj
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Centril authored Jun 27, 2019
2 parents 2a0a6a4 + 5cb841d commit cf53bc6
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 9 deletions.
1 change: 0 additions & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5795,7 +5795,6 @@ impl<'a> LoweringContext<'a> {
err.span_label(item_sp, "this is not `async`");
}
err.emit();
return hir::ExprKind::Err;
}
}
let span = self.mark_span_with_reason(
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1713,7 +1713,7 @@ pub enum GeneratorMovability {
}

/// The yield kind that caused an `ExprKind::Yield`.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub enum YieldSource {
/// An `<expr>.await`.
Await,
Expand Down
20 changes: 16 additions & 4 deletions src/librustc_typeck/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Index(ref base, ref idx) => {
self.check_expr_index(base, idx, needs, expr)
}
ExprKind::Yield(ref value, _) => {
self.check_expr_yield(value, expr)
ExprKind::Yield(ref value, ref src) => {
self.check_expr_yield(value, expr, src)
}
hir::ExprKind::Err => {
tcx.types.err
Expand Down Expand Up @@ -1541,12 +1541,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

fn check_expr_yield(&self, value: &'tcx hir::Expr, expr: &'tcx hir::Expr) -> Ty<'tcx> {
fn check_expr_yield(
&self,
value: &'tcx hir::Expr,
expr: &'tcx hir::Expr,
src: &'tcx hir::YieldSource
) -> Ty<'tcx> {
match self.yield_ty {
Some(ty) => {
self.check_expr_coercable_to_type(&value, ty);
}
None => {
// Given that this `yield` expression was generated as a result of lowering a `.await`,
// we know that the yield type must be `()`; however, the context won't contain this
// information. Hence, we check the source of the yield expression here and check its
// value's type against `()` (this check should always hold).
None if src == &hir::YieldSource::Await => {
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
}
_ => {
struct_span_err!(self.tcx.sess, expr.span, E0627,
"yield statement outside of generator literal").emit();
}
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/async-await/issues/issue-51719.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
async fn foo() {}

fn make_generator() {
let _gen = || foo.await; //~ ERROR `await` is only allowed inside `async` functions and blocks
let _gen = || foo().await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
}

fn main() {}
4 changes: 2 additions & 2 deletions src/test/ui/async-await/issues/issue-51719.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-51719.rs:10:19
|
LL | let _gen = || foo.await;
| -- ^^^^^^^^^ only allowed inside `async` functions and blocks
LL | let _gen = || foo().await;
| -- ^^^^^^^^^^^ only allowed inside `async` functions and blocks
| |
| this is not `async`

Expand Down
19 changes: 19 additions & 0 deletions src/test/ui/async-await/issues/issue-62009.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// edition:2018

#![feature(async_await)]

async fn print_dur() {}

fn main() {
async { let (); }.await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
async {
//~^ ERROR `await` is only allowed inside `async` functions and blocks
let task1 = print_dur().await;
}.await;
(async || 2333)().await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
(|_| 2333).await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
//~^^ ERROR
}
49 changes: 49 additions & 0 deletions src/test/ui/async-await/issues/issue-62009.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:8:5
|
LL | fn main() {
| ---- this is not `async`
LL | async { let (); }.await;
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:10:5
|
LL | fn main() {
| ---- this is not `async`
...
LL | / async {
LL | |
LL | | let task1 = print_dur().await;
LL | | }.await;
| |___________^ only allowed inside `async` functions and blocks

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:14:5
|
LL | fn main() {
| ---- this is not `async`
...
LL | (async || 2333)().await;
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:16:5
|
LL | fn main() {
| ---- this is not `async`
...
LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks

error[E0277]: the trait bound `[closure@$DIR/issue-62009.rs:16:5: 16:15]: std::future::Future` is not satisfied
--> $DIR/issue-62009.rs:16:5
|
LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009.rs:16:5: 16:15]`
|
= note: required by `std::future::poll_with_tls_context`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0277`.

0 comments on commit cf53bc6

Please sign in to comment.