diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-08-10 14:16:57 +0200 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-08-10 20:24:42 +0200 |
| commit | 9d739ca12d88c3985cd78d4af027d48ce2254e18 (patch) | |
| tree | 0492ba033137e27699b8adc7e28763a1785c6856 | |
| parent | c817596c694579667d3e2ee207064ae273e84940 (diff) | |
| download | rust-9d739ca12d88c3985cd78d4af027d48ce2254e18.tar.gz rust-9d739ca12d88c3985cd78d4af027d48ce2254e18.zip | |
lowering: extract lower_expr_for
| -rw-r--r-- | src/librustc/hir/lowering/expr.rs | 316 |
1 files changed, 163 insertions, 153 deletions
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index 90bc6a3ad77..0c626d6b15f 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -533,174 +533,184 @@ impl LoweringContext<'_> { // Desugar `ExprForLoop` // from: `[opt_ident]: for <pat> in <head> <body>` ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => { - // to: - // - // { - // let result = match ::std::iter::IntoIterator::into_iter(<head>) { - // mut iter => { - // [opt_ident]: loop { - // let mut __next; - // match ::std::iter::Iterator::next(&mut iter) { - // ::std::option::Option::Some(val) => __next = val, - // ::std::option::Option::None => break - // }; - // let <pat> = __next; - // StmtKind::Expr(<body>); - // } - // } - // }; - // result - // } - - // expand <head> - let mut head = self.lower_expr(head); - let head_sp = head.span; - let desugared_span = self.mark_span_with_reason( - DesugaringKind::ForLoop, - head_sp, - None, - ); - head.span = desugared_span; - - let iter = Ident::with_empty_ctxt(sym::iter); - - let next_ident = Ident::with_empty_ctxt(sym::__next); - let (next_pat, next_pat_hid) = self.pat_ident_binding_mode( - desugared_span, - next_ident, - hir::BindingAnnotation::Mutable, - ); - - // `::std::option::Option::Some(val) => __next = val` - let pat_arm = { - let val_ident = Ident::with_empty_ctxt(sym::val); - let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident); - let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid)); - let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid)); - let assign = P(self.expr( - pat.span, - hir::ExprKind::Assign(next_expr, val_expr), - ThinVec::new(), - )); - let some_pat = self.pat_some(pat.span, val_pat); - self.arm(hir_vec![some_pat], assign) - }; + return self.lower_expr_for(e, pat, head, body, opt_label); + } + ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr), + ExprKind::Mac(_) => panic!("Shouldn't exist here"), + }; - // `::std::option::Option::None => break` - let break_arm = { - let break_expr = - self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new())); - let pat = self.pat_none(e.span); - self.arm(hir_vec![pat], break_expr) - }; + hir::Expr { + hir_id: self.lower_node_id(e.id), + node: kind, + span: e.span, + attrs: e.attrs.clone(), + } + } - // `mut iter` - let (iter_pat, iter_pat_nid) = self.pat_ident_binding_mode( - desugared_span, - iter, - hir::BindingAnnotation::Mutable - ); + /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into: + /// ```rust + /// { + /// let result = match ::std::iter::IntoIterator::into_iter(<head>) { + /// mut iter => { + /// [opt_ident]: loop { + /// let mut __next; + /// match ::std::iter::Iterator::next(&mut iter) { + /// ::std::option::Option::Some(val) => __next = val, + /// ::std::option::Option::None => break + /// }; + /// let <pat> = __next; + /// StmtKind::Expr(<body>); + /// } + /// } + /// }; + /// result + /// } + /// ``` + fn lower_expr_for( + &mut self, + e: &Expr, + pat: &Pat, + head: &Expr, + body: &Block, + opt_label: Option<Label>, + ) -> hir::Expr { + // expand <head> + let mut head = self.lower_expr(head); + let head_sp = head.span; + let desugared_span = self.mark_span_with_reason( + DesugaringKind::ForLoop, + head_sp, + None, + ); + head.span = desugared_span; - // `match ::std::iter::Iterator::next(&mut iter) { ... }` - let match_expr = { - let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid)); - let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter); - let next_path = &[sym::iter, sym::Iterator, sym::next]; - let next_expr = P(self.expr_call_std_path( - head_sp, - next_path, - hir_vec![ref_mut_iter], - )); - let arms = hir_vec![pat_arm, break_arm]; - - self.expr_match(head_sp, next_expr, arms, hir::MatchSource::ForLoopDesugar) - }; - let match_stmt = self.stmt_expr(head_sp, match_expr); + let iter = Ident::with_empty_ctxt(sym::iter); - let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid)); + let next_ident = Ident::with_empty_ctxt(sym::__next); + let (next_pat, next_pat_hid) = self.pat_ident_binding_mode( + desugared_span, + next_ident, + hir::BindingAnnotation::Mutable, + ); - // `let mut __next` - let next_let = self.stmt_let_pat( - ThinVec::new(), - desugared_span, - None, - next_pat, - hir::LocalSource::ForLoopDesugar, - ); + // `::std::option::Option::Some(val) => __next = val` + let pat_arm = { + let val_ident = Ident::with_empty_ctxt(sym::val); + let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident); + let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid)); + let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid)); + let assign = P(self.expr( + pat.span, + hir::ExprKind::Assign(next_expr, val_expr), + ThinVec::new(), + )); + let some_pat = self.pat_some(pat.span, val_pat); + self.arm(hir_vec![some_pat], assign) + }; - // `let <pat> = __next` - let pat = self.lower_pat(pat); - let pat_let = self.stmt_let_pat( - ThinVec::new(), - head_sp, - Some(next_expr), - pat, - hir::LocalSource::ForLoopDesugar, - ); + // `::std::option::Option::None => break` + let break_arm = { + let break_expr = + self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new())); + let pat = self.pat_none(e.span); + self.arm(hir_vec![pat], break_expr) + }; - let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); - let body_expr = self.expr_block(body_block, ThinVec::new()); - let body_stmt = self.stmt_expr(body.span, body_expr); + // `mut iter` + let (iter_pat, iter_pat_nid) = self.pat_ident_binding_mode( + desugared_span, + iter, + hir::BindingAnnotation::Mutable + ); - let loop_block = P(self.block_all( - e.span, - hir_vec![next_let, match_stmt, pat_let, body_stmt], - None, - )); + // `match ::std::iter::Iterator::next(&mut iter) { ... }` + let match_expr = { + let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid)); + let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter); + let next_path = &[sym::iter, sym::Iterator, sym::next]; + let next_expr = P(self.expr_call_std_path( + head_sp, + next_path, + hir_vec![ref_mut_iter], + )); + let arms = hir_vec![pat_arm, break_arm]; - // `[opt_ident]: loop { ... }` - let loop_expr = hir::ExprKind::Loop( - loop_block, - self.lower_label(opt_label), - hir::LoopSource::ForLoop, - ); - let loop_expr = P(hir::Expr { - hir_id: self.lower_node_id(e.id), - node: loop_expr, - span: e.span, - attrs: ThinVec::new(), - }); - - // `mut iter => { ... }` - let iter_arm = self.arm(hir_vec![iter_pat], loop_expr); - - // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }` - let into_iter_expr = { - let into_iter_path = - &[sym::iter, sym::IntoIterator, sym::into_iter]; - P(self.expr_call_std_path( - head_sp, - into_iter_path, - hir_vec![head], - )) - }; + self.expr_match(head_sp, next_expr, arms, hir::MatchSource::ForLoopDesugar) + }; + let match_stmt = self.stmt_expr(head_sp, match_expr); - let match_expr = P(self.expr_match( - head_sp, - into_iter_expr, - hir_vec![iter_arm], - hir::MatchSource::ForLoopDesugar, - )); + let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid)); - // This is effectively `{ let _result = ...; _result }`. - // The construct was introduced in #21984 and is necessary to make sure that - // temporaries in the `head` expression are dropped and do not leak to the - // surrounding scope of the `match` since the `match` is not a terminating scope. - // - // Also, add the attributes to the outer returned expr node. - return self.expr_drop_temps(head_sp, match_expr, e.attrs.clone()) - } + // `let mut __next` + let next_let = self.stmt_let_pat( + ThinVec::new(), + desugared_span, + None, + next_pat, + hir::LocalSource::ForLoopDesugar, + ); - ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr), - ExprKind::Mac(_) => panic!("Shouldn't exist here"), - }; + // `let <pat> = __next` + let pat = self.lower_pat(pat); + let pat_let = self.stmt_let_pat( + ThinVec::new(), + head_sp, + Some(next_expr), + pat, + hir::LocalSource::ForLoopDesugar, + ); - hir::Expr { + let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); + let body_expr = self.expr_block(body_block, ThinVec::new()); + let body_stmt = self.stmt_expr(body.span, body_expr); + + let loop_block = P(self.block_all( + e.span, + hir_vec![next_let, match_stmt, pat_let, body_stmt], + None, + )); + + // `[opt_ident]: loop { ... }` + let loop_expr = hir::ExprKind::Loop( + loop_block, + self.lower_label(opt_label), + hir::LoopSource::ForLoop, + ); + let loop_expr = P(hir::Expr { hir_id: self.lower_node_id(e.id), - node: kind, + node: loop_expr, span: e.span, - attrs: e.attrs.clone(), - } + attrs: ThinVec::new(), + }); + + // `mut iter => { ... }` + let iter_arm = self.arm(hir_vec![iter_pat], loop_expr); + + // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }` + let into_iter_expr = { + let into_iter_path = + &[sym::iter, sym::IntoIterator, sym::into_iter]; + P(self.expr_call_std_path( + head_sp, + into_iter_path, + hir_vec![head], + )) + }; + + let match_expr = P(self.expr_match( + head_sp, + into_iter_expr, + hir_vec![iter_arm], + hir::MatchSource::ForLoopDesugar, + )); + + // This is effectively `{ let _result = ...; _result }`. + // The construct was introduced in #21984 and is necessary to make sure that + // temporaries in the `head` expression are dropped and do not leak to the + // surrounding scope of the `match` since the `match` is not a terminating scope. + // + // Also, add the attributes to the outer returned expr node. + self.expr_drop_temps(head_sp, match_expr, e.attrs.clone()) } /// Desugar `ExprKind::Try` from: `<expr>?` into: |
