]> git.lizzy.rs Git - rust.git/commitdiff
lowering: move lower_await -> expr.rs
authorMazdak Farrokhzad <twingoow@gmail.com>
Sat, 10 Aug 2019 13:01:38 +0000 (15:01 +0200)
committerMazdak Farrokhzad <twingoow@gmail.com>
Sat, 10 Aug 2019 18:24:42 +0000 (20:24 +0200)
src/librustc/hir/lowering.rs
src/librustc/hir/lowering/expr.rs

index 2abcbc9cfdc3393474aa5fffac9f65e1e67e2ca8..5793dc019c37bd59e110f6773f6d2c4fca9dcd3c 100644 (file)
@@ -5125,168 +5125,6 @@ fn wrap_in_try_constructor(
                                             ThinVec::new()));
         P(self.expr_call(e.span, from_err, hir_vec![e]))
     }
-
-    fn lower_await(
-        &mut self,
-        await_span: Span,
-        expr: &ast::Expr,
-    ) -> hir::ExprKind {
-        // to:
-        //
-        // {
-        //     let mut pinned = <expr>;
-        //     loop {
-        //         match ::std::future::poll_with_tls_context(unsafe {
-        //             ::std::pin::Pin::new_unchecked(&mut pinned)
-        //         }) {
-        //             ::std::task::Poll::Ready(result) => break result,
-        //             ::std::task::Poll::Pending => {},
-        //         }
-        //         yield ();
-        //     }
-        // }
-        match self.generator_kind {
-            Some(hir::GeneratorKind::Async) => {},
-            Some(hir::GeneratorKind::Gen) |
-            None => {
-                let mut err = struct_span_err!(
-                    self.sess,
-                    await_span,
-                    E0728,
-                    "`await` is only allowed inside `async` functions and blocks"
-                );
-                err.span_label(await_span, "only allowed inside `async` functions and blocks");
-                if let Some(item_sp) = self.current_item {
-                    err.span_label(item_sp, "this is not `async`");
-                }
-                err.emit();
-            }
-        }
-        let span = self.mark_span_with_reason(
-            DesugaringKind::Await,
-            await_span,
-            None,
-        );
-        let gen_future_span = self.mark_span_with_reason(
-            DesugaringKind::Await,
-            await_span,
-            self.allow_gen_future.clone(),
-        );
-
-        // let mut pinned = <expr>;
-        let expr = P(self.lower_expr(expr));
-        let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
-        let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
-            span,
-            pinned_ident,
-            hir::BindingAnnotation::Mutable,
-        );
-        let pinned_let = self.stmt_let_pat(
-            ThinVec::new(),
-            span,
-            Some(expr),
-            pinned_pat,
-            hir::LocalSource::AwaitDesugar,
-        );
-
-        // ::std::future::poll_with_tls_context(unsafe {
-        //     ::std::pin::Pin::new_unchecked(&mut pinned)
-        // })`
-        let poll_expr = {
-            let pinned = P(self.expr_ident(span, pinned_ident, pinned_pat_hid));
-            let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
-            let pin_ty_id = self.next_id();
-            let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
-                pin_ty_id,
-                span,
-                &[sym::pin, sym::Pin],
-                "new_unchecked",
-                hir_vec![ref_mut_pinned],
-            );
-            let new_unchecked = P(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
-            let unsafe_expr = self.expr_unsafe(new_unchecked);
-            P(self.expr_call_std_path(
-                gen_future_span,
-                &[sym::future, sym::poll_with_tls_context],
-                hir_vec![unsafe_expr],
-            ))
-        };
-
-        // `::std::task::Poll::Ready(result) => break result`
-        let loop_node_id = self.sess.next_node_id();
-        let loop_hir_id = self.lower_node_id(loop_node_id);
-        let ready_arm = {
-            let x_ident = Ident::with_empty_ctxt(sym::result);
-            let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
-            let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
-            let ready_pat = self.pat_std_enum(
-                span,
-                &[sym::task, sym::Poll, sym::Ready],
-                hir_vec![x_pat],
-            );
-            let break_x = self.with_loop_scope(loop_node_id, |this| {
-                let expr_break = hir::ExprKind::Break(
-                    this.lower_loop_destination(None),
-                    Some(x_expr),
-                );
-                P(this.expr(await_span, expr_break, ThinVec::new()))
-            });
-            self.arm(hir_vec![ready_pat], break_x)
-        };
-
-        // `::std::task::Poll::Pending => {}`
-        let pending_arm = {
-            let pending_pat = self.pat_std_enum(
-                span,
-                &[sym::task, sym::Poll, sym::Pending],
-                hir_vec![],
-            );
-            let empty_block = P(self.expr_block_empty(span));
-            self.arm(hir_vec![pending_pat], empty_block)
-        };
-
-        let match_stmt = {
-            let match_expr = self.expr_match(
-                span,
-                poll_expr,
-                hir_vec![ready_arm, pending_arm],
-                hir::MatchSource::AwaitDesugar,
-            );
-            self.stmt_expr(span, match_expr)
-        };
-
-        let yield_stmt = {
-            let unit = self.expr_unit(span);
-            let yield_expr = self.expr(
-                span,
-                hir::ExprKind::Yield(P(unit), hir::YieldSource::Await),
-                ThinVec::new(),
-            );
-            self.stmt_expr(span, yield_expr)
-        };
-
-        let loop_block = P(self.block_all(
-            span,
-            hir_vec![match_stmt, yield_stmt],
-            None,
-        ));
-
-        let loop_expr = P(hir::Expr {
-            hir_id: loop_hir_id,
-            node: hir::ExprKind::Loop(
-                loop_block,
-                None,
-                hir::LoopSource::Loop,
-            ),
-            span,
-            attrs: ThinVec::new(),
-        });
-
-        hir::ExprKind::Block(
-            P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))),
-            None,
-        )
-    }
 }
 
 fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
index 3bf6402bff5665d203da2bf576f984432e7e6949..2ac8889e0040f3a3e386a32da1b9af7aa2b04512 100644 (file)
@@ -263,7 +263,7 @@ pub(super) fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     })
                 })
             }
-            ExprKind::Await(ref expr) => self.lower_await(e.span, expr),
+            ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
             ExprKind::Closure(
                 capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
             ) => if let IsAsync::Async { closure_id, .. } = asyncness {
@@ -375,6 +375,165 @@ pub(super) fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
         }
     }
 
+    /// Desugar `<expr>.await` into:
+    /// ```rust
+    /// {
+    ///     let mut pinned = <expr>;
+    ///     loop {
+    ///         match ::std::future::poll_with_tls_context(unsafe {
+    ///             ::std::pin::Pin::new_unchecked(&mut pinned)
+    ///         }) {
+    ///             ::std::task::Poll::Ready(result) => break result,
+    ///             ::std::task::Poll::Pending => {},
+    ///         }
+    ///         yield ();
+    ///     }
+    /// }
+    /// ```
+    fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind {
+        match self.generator_kind {
+            Some(hir::GeneratorKind::Async) => {},
+            Some(hir::GeneratorKind::Gen) |
+            None => {
+                let mut err = struct_span_err!(
+                    self.sess,
+                    await_span,
+                    E0728,
+                    "`await` is only allowed inside `async` functions and blocks"
+                );
+                err.span_label(await_span, "only allowed inside `async` functions and blocks");
+                if let Some(item_sp) = self.current_item {
+                    err.span_label(item_sp, "this is not `async`");
+                }
+                err.emit();
+            }
+        }
+        let span = self.mark_span_with_reason(
+            DesugaringKind::Await,
+            await_span,
+            None,
+        );
+        let gen_future_span = self.mark_span_with_reason(
+            DesugaringKind::Await,
+            await_span,
+            self.allow_gen_future.clone(),
+        );
+
+        // let mut pinned = <expr>;
+        let expr = P(self.lower_expr(expr));
+        let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
+        let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
+            span,
+            pinned_ident,
+            hir::BindingAnnotation::Mutable,
+        );
+        let pinned_let = self.stmt_let_pat(
+            ThinVec::new(),
+            span,
+            Some(expr),
+            pinned_pat,
+            hir::LocalSource::AwaitDesugar,
+        );
+
+        // ::std::future::poll_with_tls_context(unsafe {
+        //     ::std::pin::Pin::new_unchecked(&mut pinned)
+        // })`
+        let poll_expr = {
+            let pinned = P(self.expr_ident(span, pinned_ident, pinned_pat_hid));
+            let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
+            let pin_ty_id = self.next_id();
+            let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
+                pin_ty_id,
+                span,
+                &[sym::pin, sym::Pin],
+                "new_unchecked",
+                hir_vec![ref_mut_pinned],
+            );
+            let new_unchecked = P(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
+            let unsafe_expr = self.expr_unsafe(new_unchecked);
+            P(self.expr_call_std_path(
+                gen_future_span,
+                &[sym::future, sym::poll_with_tls_context],
+                hir_vec![unsafe_expr],
+            ))
+        };
+
+        // `::std::task::Poll::Ready(result) => break result`
+        let loop_node_id = self.sess.next_node_id();
+        let loop_hir_id = self.lower_node_id(loop_node_id);
+        let ready_arm = {
+            let x_ident = Ident::with_empty_ctxt(sym::result);
+            let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
+            let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
+            let ready_pat = self.pat_std_enum(
+                span,
+                &[sym::task, sym::Poll, sym::Ready],
+                hir_vec![x_pat],
+            );
+            let break_x = self.with_loop_scope(loop_node_id, |this| {
+                let expr_break = hir::ExprKind::Break(
+                    this.lower_loop_destination(None),
+                    Some(x_expr),
+                );
+                P(this.expr(await_span, expr_break, ThinVec::new()))
+            });
+            self.arm(hir_vec![ready_pat], break_x)
+        };
+
+        // `::std::task::Poll::Pending => {}`
+        let pending_arm = {
+            let pending_pat = self.pat_std_enum(
+                span,
+                &[sym::task, sym::Poll, sym::Pending],
+                hir_vec![],
+            );
+            let empty_block = P(self.expr_block_empty(span));
+            self.arm(hir_vec![pending_pat], empty_block)
+        };
+
+        let match_stmt = {
+            let match_expr = self.expr_match(
+                span,
+                poll_expr,
+                hir_vec![ready_arm, pending_arm],
+                hir::MatchSource::AwaitDesugar,
+            );
+            self.stmt_expr(span, match_expr)
+        };
+
+        let yield_stmt = {
+            let unit = self.expr_unit(span);
+            let yield_expr = self.expr(
+                span,
+                hir::ExprKind::Yield(P(unit), hir::YieldSource::Await),
+                ThinVec::new(),
+            );
+            self.stmt_expr(span, yield_expr)
+        };
+
+        let loop_block = P(self.block_all(
+            span,
+            hir_vec![match_stmt, yield_stmt],
+            None,
+        ));
+
+        let loop_expr = P(hir::Expr {
+            hir_id: loop_hir_id,
+            node: hir::ExprKind::Loop(
+                loop_block,
+                None,
+                hir::LoopSource::Loop,
+            ),
+            span,
+            attrs: ThinVec::new(),
+        });
+
+        hir::ExprKind::Block(
+            P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))),
+            None,
+        )
+    }
+
     fn lower_expr_closure(
         &mut self,
         capture_clause: CaptureBy,