From 5cb841d72e70f92fc4318833db4824d07ab4c911 Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Wed, 26 Jun 2019 13:48:41 +0100 Subject: [PATCH] Don't ICE on item in `.await` expression --- src/librustc/hir/lowering.rs | 1 - src/librustc/hir/mod.rs | 2 +- src/librustc_typeck/check/expr.rs | 20 ++++++-- src/test/ui/async-await/issues/issue-51719.rs | 3 +- .../ui/async-await/issues/issue-51719.stderr | 4 +- src/test/ui/async-await/issues/issue-62009.rs | 19 +++++++ .../ui/async-await/issues/issue-62009.stderr | 49 +++++++++++++++++++ 7 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/async-await/issues/issue-62009.rs create mode 100644 src/test/ui/async-await/issues/issue-62009.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1b8e2999afe6a..9c4a208f0f9fc 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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( diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2b46170a6d232..6df1c2d8c77e5 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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 `.await`. Await, diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 85da325197143..21fa219a1cab2 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -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 @@ -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(); } diff --git a/src/test/ui/async-await/issues/issue-51719.rs b/src/test/ui/async-await/issues/issue-51719.rs index 5966edd0bf098..361a49c2774ec 100644 --- a/src/test/ui/async-await/issues/issue-51719.rs +++ b/src/test/ui/async-await/issues/issue-51719.rs @@ -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() {} diff --git a/src/test/ui/async-await/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr index c06165b24468f..2a9fb6cf0df6e 100644 --- a/src/test/ui/async-await/issues/issue-51719.stderr +++ b/src/test/ui/async-await/issues/issue-51719.stderr @@ -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` diff --git a/src/test/ui/async-await/issues/issue-62009.rs b/src/test/ui/async-await/issues/issue-62009.rs new file mode 100644 index 0000000000000..e2d58cac24d94 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62009.rs @@ -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 +} diff --git a/src/test/ui/async-await/issues/issue-62009.stderr b/src/test/ui/async-await/issues/issue-62009.stderr new file mode 100644 index 0000000000000..53d1f34fe4f9b --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62009.stderr @@ -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`.