]> git.lizzy.rs Git - rust.git/commitdiff
Don't ICE on item in `.await` expression
authorNathan Corbyn <me@nathancorbyn.com>
Wed, 26 Jun 2019 12:48:41 +0000 (13:48 +0100)
committerNathan Corbyn <me@nathancorbyn.com>
Wed, 26 Jun 2019 14:49:10 +0000 (15:49 +0100)
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc_typeck/check/expr.rs
src/test/ui/async-await/issues/issue-51719.rs
src/test/ui/async-await/issues/issue-51719.stderr
src/test/ui/async-await/issues/issue-62009.rs [new file with mode: 0644]
src/test/ui/async-await/issues/issue-62009.stderr [new file with mode: 0644]

index 1b8e2999afe6ae3060a669bafcd482d51cbca856..9c4a208f0f9fc92fb4e193ab508918d06097b3ae 100644 (file)
@@ -5795,7 +5795,6 @@ fn lower_await(
                     err.span_label(item_sp, "this is not `async`");
                 }
                 err.emit();
-                return hir::ExprKind::Err;
             }
         }
         let span = self.mark_span_with_reason(
index 2b46170a6d2322cc3e1313aff79b3e5d36c4c4b1..6df1c2d8c77e5e3a69e7018622165f61b380196e 100644 (file)
@@ -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,
index 85da3251971430ddbe47228718a5f5c4380bdf4e..21fa219a1cab27ee1e63baeb361eb68406834bfb 100644 (file)
@@ -295,8 +295,8 @@ fn check_expr_kind(
             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 @@ fn check_expr_index(
         }
     }
 
-    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();
             }
index 5966edd0bf09856643ee0d12b73aa2c2104a9b9f..361a49c2774ecc778ee087732591d1b10d081345 100644 (file)
@@ -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() {}
index c06165b24468fb97f6b655d597336d699380c0e6..2a9fb6cf0df6e511be761d89149d2b8fc97b9144 100644 (file)
@@ -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 (file)
index 0000000..e2d58ca
--- /dev/null
@@ -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 (file)
index 0000000..53d1f34
--- /dev/null
@@ -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`.