about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNathan Corbyn <me@nathancorbyn.com>2019-06-26 13:48:41 +0100
committerNathan Corbyn <me@nathancorbyn.com>2019-06-26 15:49:10 +0100
commit5cb841d72e70f92fc4318833db4824d07ab4c911 (patch)
tree521b90e280f8e5e638c8adddfaf17f8043bd7850
parentd3e2cec29225a46298ec4ebf082f34ebd7cfeecf (diff)
downloadrust-5cb841d72e70f92fc4318833db4824d07ab4c911.tar.gz
rust-5cb841d72e70f92fc4318833db4824d07ab4c911.zip
Don't ICE on item in `.await` expression
-rw-r--r--src/librustc/hir/lowering.rs1
-rw-r--r--src/librustc/hir/mod.rs2
-rw-r--r--src/librustc_typeck/check/expr.rs20
-rw-r--r--src/test/ui/async-await/issues/issue-51719.rs3
-rw-r--r--src/test/ui/async-await/issues/issue-51719.stderr4
-rw-r--r--src/test/ui/async-await/issues/issue-62009.rs19
-rw-r--r--src/test/ui/async-await/issues/issue-62009.stderr49
7 files changed, 89 insertions, 9 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 1b8e2999afe..9c4a208f0f9 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 2b46170a6d2..6df1c2d8c77 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 `<expr>.await`.
     Await,
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 85da3251971..21fa219a1ca 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 5966edd0bf0..361a49c2774 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 c06165b2446..2a9fb6cf0df 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 00000000000..e2d58cac24d
--- /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 00000000000..53d1f34fe4f
--- /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`.