]> git.lizzy.rs Git - rust.git/commitdiff
refactorings of `lowering` that make it more amenable to using `&mut`
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 12 Nov 2015 17:31:05 +0000 (12:31 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 19 Nov 2015 00:22:17 +0000 (19:22 -0500)
instead of `Cell` (but stop short of actualling switching to `&mut`)

src/librustc_front/lowering.rs

index 230fb93fd4d14ad20ef27a3654a7edead6498571..250379d2d7efc3d2df58f6b4d421b8bece9c75a9 100644 (file)
@@ -875,19 +875,16 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
     })
 }
 
-// RAII utility for setting and unsetting the cached id.
-struct CachedIdSetter<'a> {
-    reset: bool,
-    lctx: &'a LoweringContext<'a>,
-}
-
-impl<'a> CachedIdSetter<'a> {
-    fn new(lctx: &'a LoweringContext, expr_id: NodeId) -> CachedIdSetter<'a> {
-        // Only reset the id if it was previously 0, i.e., was not cached.
-        // If it was cached, we are in a nested node, but our id count will
-        // still count towards the parent's count.
-        let reset_cached_id = lctx.cached_id.get() == 0;
-
+// Utility fn for setting and unsetting the cached id.
+fn cache_ids<'a, OP, R>(lctx: &LoweringContext, expr_id: NodeId, op: OP) -> R
+    where OP: FnOnce(&LoweringContext) -> R
+{
+    // Only reset the id if it was previously 0, i.e., was not cached.
+    // If it was cached, we are in a nested node, but our id count will
+    // still count towards the parent's count.
+    let reset_cached_id = lctx.cached_id.get() == 0;
+
+    {
         let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
 
         if id_cache.contains_key(&expr_id) {
@@ -907,21 +904,16 @@ fn new(lctx: &'a LoweringContext, expr_id: NodeId) -> CachedIdSetter<'a> {
             id_cache.insert(expr_id, next_id);
             lctx.gensym_key.set(next_id);
         }
-
-        CachedIdSetter {
-            reset: reset_cached_id,
-            lctx: lctx,
-        }
     }
-}
 
-impl<'a> Drop for CachedIdSetter<'a> {
-    fn drop(&mut self) {
-        if self.reset {
-            self.lctx.cached_id.set(0);
-            self.lctx.gensym_key.set(0);
-        }
+    let result = op(lctx);
+
+    if reset_cached_id {
+        lctx.cached_id.set(0);
+        lctx.gensym_key.set(0);
     }
+
+    result
 }
 
 pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
@@ -959,129 +951,141 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
                 //     InPlace::finalize(place)
                 // })
-                let _old_cached = CachedIdSetter::new(lctx, e.id);
+                return cache_ids(lctx, e.id, |lctx| {
+                    let placer_expr = lower_expr(lctx, placer);
+                    let value_expr = lower_expr(lctx, value_expr);
+
+                    let placer_ident = lctx.str_to_ident("placer");
+                    let place_ident = lctx.str_to_ident("place");
+                    let p_ptr_ident = lctx.str_to_ident("p_ptr");
+
+                    let make_place = ["ops", "Placer", "make_place"];
+                    let place_pointer = ["ops", "Place", "pointer"];
+                    let move_val_init = ["intrinsics", "move_val_init"];
+                    let inplace_finalize = ["ops", "InPlace", "finalize"];
+
+                    let make_call = |lctx: &LoweringContext, p, args| {
+                        let path = core_path(lctx, e.span, p);
+                        let path = expr_path(lctx, path);
+                        expr_call(lctx, e.span, path, args)
+                    };
 
-                let placer_expr = lower_expr(lctx, placer);
-                let value_expr = lower_expr(lctx, value_expr);
+                    let mk_stmt_let = |lctx: &LoweringContext, bind, expr| {
+                        stmt_let(lctx, e.span, false, bind, expr)
+                    };
 
-                let placer_ident = lctx.str_to_ident("placer");
-                let agent_ident = lctx.str_to_ident("place");
-                let p_ptr_ident = lctx.str_to_ident("p_ptr");
+                    let mk_stmt_let_mut = |lctx: &LoweringContext, bind, expr| {
+                        stmt_let(lctx, e.span, true, bind, expr)
+                    };
 
-                let make_place = ["ops", "Placer", "make_place"];
-                let place_pointer = ["ops", "Place", "pointer"];
-                let move_val_init = ["intrinsics", "move_val_init"];
-                let inplace_finalize = ["ops", "InPlace", "finalize"];
+                    // let placer = <placer_expr> ;
+                    let s1 = {
+                        let placer_expr = signal_block_expr(lctx,
+                                                            vec![],
+                                                            placer_expr,
+                                                            e.span,
+                                                            hir::PopUnstableBlock);
+                        mk_stmt_let(lctx, placer_ident, placer_expr)
+                    };
 
-                let make_call = |lctx, p, args| {
-                    let path = core_path(lctx, e.span, p);
-                    let path = expr_path(lctx, path);
-                    expr_call(lctx, e.span, path, args)
-                };
+                    // let mut place = Placer::make_place(placer);
+                    let s2 = {
+                        let placer = expr_ident(lctx, e.span, placer_ident);
+                        let call = make_call(lctx, &make_place, vec![placer]);
+                        mk_stmt_let_mut(lctx, place_ident, call)
+                    };
 
-                let mk_stmt_let = |lctx, bind, expr| stmt_let(lctx, e.span, false, bind, expr);
-                let mk_stmt_let_mut = |lctx, bind, expr| stmt_let(lctx, e.span, true, bind, expr);
-
-                // let placer = <placer_expr> ;
-                let s1 = mk_stmt_let(lctx,
-                                     placer_ident,
-                                     signal_block_expr(lctx,
-                                                       vec![],
-                                                       placer_expr,
-                                                       e.span,
-                                                       hir::PopUnstableBlock));
-
-                // let mut place = Placer::make_place(placer);
-                let s2 = {
-                    let call = make_call(lctx,
-                                         &make_place,
-                                         vec![expr_ident(lctx, e.span, placer_ident)]);
-                    mk_stmt_let_mut(lctx, agent_ident, call)
-                };
+                    // let p_ptr = Place::pointer(&mut place);
+                    let s3 = {
+                        let agent = expr_ident(lctx, e.span, place_ident);
+                        let args = vec![expr_mut_addr_of(lctx, e.span, agent)];
+                        let call = make_call(lctx, &place_pointer, args);
+                        mk_stmt_let(lctx, p_ptr_ident, call)
+                    };
 
-                // let p_ptr = Place::pointer(&mut place);
-                let s3 = {
-                    let args = vec![expr_mut_addr_of(lctx,
-                                                     e.span,
-                                                     expr_ident(lctx, e.span, agent_ident))];
-                    let call = make_call(lctx, &place_pointer, args);
-                    mk_stmt_let(lctx, p_ptr_ident, call)
-                };
+                    // pop_unsafe!(EXPR));
+                    let pop_unsafe_expr = {
+                        let value_expr = signal_block_expr(lctx,
+                                                           vec![],
+                                                           value_expr,
+                                                           e.span,
+                                                           hir::PopUnstableBlock);
+                        signal_block_expr(lctx,
+                                          vec![],
+                                          value_expr,
+                                          e.span,
+                                          hir::PopUnsafeBlock(hir::CompilerGenerated))
+                    };
 
-                // pop_unsafe!(EXPR));
-                let pop_unsafe_expr =
-                    signal_block_expr(lctx,
-                                      vec![],
-                                      signal_block_expr(lctx,
-                                                        vec![],
-                                                        value_expr,
-                                                        e.span,
-                                                        hir::PopUnstableBlock),
-                                      e.span,
-                                      hir::PopUnsafeBlock(hir::CompilerGenerated));
+                    // push_unsafe!({
+                    //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
+                    //     InPlace::finalize(place)
+                    // })
+                    let expr = {
+                        let ptr = expr_ident(lctx, e.span, p_ptr_ident);
+                        let call_move_val_init =
+                            hir::StmtSemi(
+                                make_call(lctx, &move_val_init, vec![ptr, pop_unsafe_expr]),
+                                lctx.next_id());
+                        let call_move_val_init = respan(e.span, call_move_val_init);
+
+                        let place = expr_ident(lctx, e.span, place_ident);
+                        let call = make_call(lctx, &inplace_finalize, vec![place]);
+                        signal_block_expr(lctx,
+                                          vec![P(call_move_val_init)],
+                                          call,
+                                          e.span,
+                                          hir::PushUnsafeBlock(hir::CompilerGenerated))
+                    };
 
-                // push_unsafe!({
-                //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
-                //     InPlace::finalize(place)
-                // })
-                let expr = {
-                    let call_move_val_init =
-                        hir::StmtSemi(make_call(lctx,
-                                                &move_val_init,
-                                                vec![expr_ident(lctx, e.span, p_ptr_ident),
-                                                     pop_unsafe_expr]),
-                                      lctx.next_id());
-                    let call_move_val_init = respan(e.span, call_move_val_init);
-
-                    let call = make_call(lctx,
-                                         &inplace_finalize,
-                                         vec![expr_ident(lctx, e.span, agent_ident)]);
                     signal_block_expr(lctx,
-                                      vec![P(call_move_val_init)],
-                                      call,
+                                      vec![s1, s2, s3],
+                                      expr,
                                       e.span,
-                                      hir::PushUnsafeBlock(hir::CompilerGenerated))
-                };
-
-                return signal_block_expr(lctx,
-                                         vec![s1, s2, s3],
-                                         expr,
-                                         e.span,
-                                         hir::PushUnstableBlock);
+                                      hir::PushUnstableBlock)
+                });
             }
 
             ExprVec(ref exprs) => {
                 hir::ExprVec(exprs.iter().map(|x| lower_expr(lctx, x)).collect())
             }
             ExprRepeat(ref expr, ref count) => {
-                hir::ExprRepeat(lower_expr(lctx, expr), lower_expr(lctx, count))
+                let expr = lower_expr(lctx, expr);
+                let count = lower_expr(lctx, count);
+                hir::ExprRepeat(expr, count)
             }
             ExprTup(ref elts) => {
                 hir::ExprTup(elts.iter().map(|x| lower_expr(lctx, x)).collect())
             }
             ExprCall(ref f, ref args) => {
-                hir::ExprCall(lower_expr(lctx, f),
-                              args.iter().map(|x| lower_expr(lctx, x)).collect())
+                let f = lower_expr(lctx, f);
+                hir::ExprCall(f, args.iter().map(|x| lower_expr(lctx, x)).collect())
             }
             ExprMethodCall(i, ref tps, ref args) => {
-                hir::ExprMethodCall(respan(i.span, i.node.name),
-                                    tps.iter().map(|x| lower_ty(lctx, x)).collect(),
-                                    args.iter().map(|x| lower_expr(lctx, x)).collect())
+                let tps = tps.iter().map(|x| lower_ty(lctx, x)).collect();
+                let args = args.iter().map(|x| lower_expr(lctx, x)).collect();
+                hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
             }
             ExprBinary(binop, ref lhs, ref rhs) => {
-                hir::ExprBinary(lower_binop(lctx, binop),
-                                lower_expr(lctx, lhs),
-                                lower_expr(lctx, rhs))
+                let binop = lower_binop(lctx, binop);
+                let lhs = lower_expr(lctx, lhs);
+                let rhs = lower_expr(lctx, rhs);
+                hir::ExprBinary(binop, lhs, rhs)
             }
             ExprUnary(op, ref ohs) => {
-                hir::ExprUnary(lower_unop(lctx, op), lower_expr(lctx, ohs))
+                let op = lower_unop(lctx, op);
+                let ohs = lower_expr(lctx, ohs);
+                hir::ExprUnary(op, ohs)
             }
             ExprLit(ref l) => hir::ExprLit(P((**l).clone())),
             ExprCast(ref expr, ref ty) => {
-                hir::ExprCast(lower_expr(lctx, expr), lower_ty(lctx, ty))
+                let expr = lower_expr(lctx, expr);
+                hir::ExprCast(expr, lower_ty(lctx, ty))
             }
             ExprAddrOf(m, ref ohs) => {
-                hir::ExprAddrOf(lower_mutability(lctx, m), lower_expr(lctx, ohs))
+                let m = lower_mutability(lctx, m);
+                let ohs = lower_expr(lctx, ohs);
+                hir::ExprAddrOf(m, ohs)
             }
             // More complicated than you might expect because the else branch
             // might be `if let`.
@@ -1089,17 +1093,20 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 let else_opt = else_opt.as_ref().map(|els| {
                     match els.node {
                         ExprIfLet(..) => {
-                            let _old_cached = CachedIdSetter::new(lctx, e.id);
-                            // wrap the if-let expr in a block
-                            let span = els.span;
-                            let blk = P(hir::Block {
-                                stmts: vec![],
-                                expr: Some(lower_expr(lctx, els)),
-                                id: lctx.next_id(),
-                                rules: hir::DefaultBlock,
-                                span: span,
-                            });
-                            expr_block(lctx, blk)
+                            cache_ids(lctx, e.id, |lctx| {
+                                // wrap the if-let expr in a block
+                                let span = els.span;
+                                let els = lower_expr(lctx, els);
+                                let id = lctx.next_id();
+                                let blk = P(hir::Block {
+                                    stmts: vec![],
+                                    expr: Some(els),
+                                    id: id,
+                                    rules: hir::DefaultBlock,
+                                    span: span,
+                                });
+                                expr_block(lctx, blk)
+                            })
                         }
                         _ => lower_expr(lctx, els),
                     }
@@ -1204,76 +1211,79 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 //     _ => [<else_opt> | ()]
                 //   }
 
-                let _old_cached = CachedIdSetter::new(lctx, e.id);
-
-                // `<pat> => <body>`
-                let pat_arm = {
-                    let body_expr = expr_block(lctx, lower_block(lctx, body));
-                    arm(vec![lower_pat(lctx, pat)], body_expr)
-                };
+                return cache_ids(lctx, e.id, |lctx| {
+                    // `<pat> => <body>`
+                    let pat_arm = {
+                        let body = lower_block(lctx, body);
+                        let body_expr = expr_block(lctx, body);
+                        arm(vec![lower_pat(lctx, pat)], body_expr)
+                    };
 
-                // `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
-                let mut else_opt = else_opt.as_ref().map(|e| lower_expr(lctx, e));
-                let else_if_arms = {
-                    let mut arms = vec![];
-                    loop {
-                        let else_opt_continue = else_opt.and_then(|els| {
-                            els.and_then(|els| {
-                                match els.node {
-                                    // else if
-                                    hir::ExprIf(cond, then, else_opt) => {
-                                        let pat_under = pat_wild(lctx, e.span);
-                                        arms.push(hir::Arm {
-                                            attrs: vec![],
-                                            pats: vec![pat_under],
-                                            guard: Some(cond),
-                                            body: expr_block(lctx, then),
-                                        });
-                                        else_opt.map(|else_opt| (else_opt, true))
+                    // `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
+                    let mut else_opt = else_opt.as_ref().map(|e| lower_expr(lctx, e));
+                    let else_if_arms = {
+                        let mut arms = vec![];
+                        loop {
+                            let else_opt_continue = else_opt.and_then(|els| {
+                                els.and_then(|els| {
+                                    match els.node {
+                                        // else if
+                                        hir::ExprIf(cond, then, else_opt) => {
+                                            let pat_under = pat_wild(lctx, e.span);
+                                            arms.push(hir::Arm {
+                                                attrs: vec![],
+                                                pats: vec![pat_under],
+                                                guard: Some(cond),
+                                                body: expr_block(lctx, then),
+                                            });
+                                            else_opt.map(|else_opt| (else_opt, true))
+                                        }
+                                        _ => Some((P(els), false)),
                                     }
-                                    _ => Some((P(els), false)),
+                                })
+                            });
+                            match else_opt_continue {
+                                Some((e, true)) => {
+                                    else_opt = Some(e);
+                                }
+                                Some((e, false)) => {
+                                    else_opt = Some(e);
+                                    break;
+                                }
+                                None => {
+                                    else_opt = None;
+                                    break;
                                 }
-                            })
-                        });
-                        match else_opt_continue {
-                            Some((e, true)) => {
-                                else_opt = Some(e);
-                            }
-                            Some((e, false)) => {
-                                else_opt = Some(e);
-                                break;
-                            }
-                            None => {
-                                else_opt = None;
-                                break;
                             }
                         }
-                    }
-                    arms
-                };
+                        arms
+                    };
 
-                let contains_else_clause = else_opt.is_some();
+                    let contains_else_clause = else_opt.is_some();
 
-                // `_ => [<else_opt> | ()]`
-                let else_arm = {
-                    let pat_under = pat_wild(lctx, e.span);
-                    let else_expr = else_opt.unwrap_or_else(|| expr_tuple(lctx, e.span, vec![]));
-                    arm(vec![pat_under], else_expr)
-                };
+                    // `_ => [<else_opt> | ()]`
+                    let else_arm = {
+                        let pat_under = pat_wild(lctx, e.span);
+                        let else_expr =
+                            else_opt.unwrap_or_else(
+                                || expr_tuple(lctx, e.span, vec![]));
+                        arm(vec![pat_under], else_expr)
+                    };
 
-                let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
-                arms.push(pat_arm);
-                arms.extend(else_if_arms);
-                arms.push(else_arm);
+                    let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
+                    arms.push(pat_arm);
+                    arms.extend(else_if_arms);
+                    arms.push(else_arm);
 
-                let match_expr = expr(lctx,
-                                      e.span,
-                                      hir::ExprMatch(lower_expr(lctx, sub_expr),
-                                                     arms,
-                                                     hir::MatchSource::IfLetDesugar {
-                                                         contains_else_clause: contains_else_clause,
-                                                     }));
-                return match_expr;
+                    let sub_expr = lower_expr(lctx, sub_expr);
+                    expr(lctx,
+                         e.span,
+                         hir::ExprMatch(sub_expr,
+                                        arms,
+                                        hir::MatchSource::IfLetDesugar {
+                                            contains_else_clause: contains_else_clause,
+                                        }))
+                });
             }
 
             // Desugar ExprWhileLet
@@ -1288,32 +1298,34 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 //     }
                 //   }
 
-                let _old_cached = CachedIdSetter::new(lctx, e.id);
-
-                // `<pat> => <body>`
-                let pat_arm = {
-                    let body_expr = expr_block(lctx, lower_block(lctx, body));
-                    arm(vec![lower_pat(lctx, pat)], body_expr)
-                };
-
-                // `_ => break`
-                let break_arm = {
-                    let pat_under = pat_wild(lctx, e.span);
-                    let break_expr = expr_break(lctx, e.span);
-                    arm(vec![pat_under], break_expr)
-                };
+                return cache_ids(lctx, e.id, |lctx| {
+                    // `<pat> => <body>`
+                    let pat_arm = {
+                        let body = lower_block(lctx, body);
+                        let body_expr = expr_block(lctx, body);
+                        arm(vec![lower_pat(lctx, pat)], body_expr)
+                    };
 
-                // `match <sub_expr> { ... }`
-                let arms = vec![pat_arm, break_arm];
-                let match_expr = expr(lctx,
-                                      e.span,
-                                      hir::ExprMatch(lower_expr(lctx, sub_expr),
-                                                     arms,
-                                                     hir::MatchSource::WhileLetDesugar));
+                    // `_ => break`
+                    let break_arm = {
+                        let pat_under = pat_wild(lctx, e.span);
+                        let break_expr = expr_break(lctx, e.span);
+                        arm(vec![pat_under], break_expr)
+                    };
 
-                // `[opt_ident]: loop { ... }`
-                let loop_block = block_expr(lctx, match_expr);
-                return expr(lctx, e.span, hir::ExprLoop(loop_block, opt_ident));
+                    // `match <sub_expr> { ... }`
+                    let arms = vec![pat_arm, break_arm];
+                    let sub_expr = lower_expr(lctx, sub_expr);
+                    let match_expr = expr(lctx,
+                                          e.span,
+                                          hir::ExprMatch(sub_expr,
+                                                         arms,
+                                                         hir::MatchSource::WhileLetDesugar));
+
+                    // `[opt_ident]: loop { ... }`
+                    let loop_block = block_expr(lctx, match_expr);
+                    expr(lctx, e.span, hir::ExprLoop(loop_block, opt_ident))
+                });
             }
 
             // Desugar ExprForLoop
@@ -1335,97 +1347,90 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 //     result
                 //   }
 
-                let _old_cached = CachedIdSetter::new(lctx, e.id);
-
-                // expand <head>
-                let head = lower_expr(lctx, head);
-
-                let iter = lctx.str_to_ident("iter");
+                return cache_ids(lctx, e.id, |lctx| {
+                    // expand <head>
+                    let head = lower_expr(lctx, head);
 
-                // `::std::option::Option::Some(<pat>) => <body>`
-                let pat_arm = {
-                    let body_block = lower_block(lctx, body);
-                    let body_span = body_block.span;
-                    let body_expr = P(hir::Expr {
-                        id: lctx.next_id(),
-                        node: hir::ExprBlock(body_block),
-                        span: body_span,
-                    });
-                    let pat = lower_pat(lctx, pat);
-                    let some_pat = pat_some(lctx, e.span, pat);
+                    let iter = lctx.str_to_ident("iter");
 
-                    arm(vec![some_pat], body_expr)
-                };
+                    // `::std::option::Option::Some(<pat>) => <body>`
+                    let pat_arm = {
+                        let body_block = lower_block(lctx, body);
+                        let body_span = body_block.span;
+                        let body_expr = P(hir::Expr {
+                            id: lctx.next_id(),
+                            node: hir::ExprBlock(body_block),
+                            span: body_span,
+                        });
+                        let pat = lower_pat(lctx, pat);
+                        let some_pat = pat_some(lctx, e.span, pat);
 
-                // `::std::option::Option::None => break`
-                let break_arm = {
-                    let break_expr = expr_break(lctx, e.span);
+                        arm(vec![some_pat], body_expr)
+                    };
 
-                    arm(vec![pat_none(lctx, e.span)], break_expr)
-                };
+                    // `::std::option::Option::None => break`
+                    let break_arm = {
+                        let break_expr = expr_break(lctx, e.span);
 
-                // `match ::std::iter::Iterator::next(&mut iter) { ... }`
-                let match_expr = {
-                    let next_path = {
-                        let strs = std_path(lctx, &["iter", "Iterator", "next"]);
+                        arm(vec![pat_none(lctx, e.span)], break_expr)
+                    };
 
-                        path_global(e.span, strs)
+                    // `match ::std::iter::Iterator::next(&mut iter) { ... }`
+                    let match_expr = {
+                        let next_path = {
+                            let strs = std_path(lctx, &["iter", "Iterator", "next"]);
+
+                            path_global(e.span, strs)
+                        };
+                        let iter = expr_ident(lctx, e.span, iter);
+                        let ref_mut_iter = expr_mut_addr_of(lctx, e.span, iter);
+                        let next_path = expr_path(lctx, next_path);
+                        let next_expr = expr_call(lctx, e.span, next_path, vec![ref_mut_iter]);
+                        let arms = vec![pat_arm, break_arm];
+
+                        expr(lctx,
+                             e.span,
+                             hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar))
                     };
-                    let ref_mut_iter = expr_mut_addr_of(lctx,
-                                                        e.span,
-                                                        expr_ident(lctx, e.span, iter));
-                    let next_expr = expr_call(lctx,
-                                              e.span,
-                                              expr_path(lctx, next_path),
-                                              vec![ref_mut_iter]);
-                    let arms = vec![pat_arm, break_arm];
 
-                    expr(lctx,
-                         e.span,
-                         hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar))
-                };
+                    // `[opt_ident]: loop { ... }`
+                    let loop_block = block_expr(lctx, match_expr);
+                    let loop_expr = expr(lctx, e.span, hir::ExprLoop(loop_block, opt_ident));
+
+                    // `mut iter => { ... }`
+                    let iter_arm = {
+                        let iter_pat = pat_ident_binding_mode(lctx,
+                                                              e.span,
+                                                              iter,
+                                                              hir::BindByValue(hir::MutMutable));
+                        arm(vec![iter_pat], loop_expr)
+                    };
 
-                // `[opt_ident]: loop { ... }`
-                let loop_block = block_expr(lctx, match_expr);
-                let loop_expr = expr(lctx, e.span, hir::ExprLoop(loop_block, opt_ident));
-
-                // `mut iter => { ... }`
-                let iter_arm = {
-                    let iter_pat = pat_ident_binding_mode(lctx,
-                                                          e.span,
-                                                          iter,
-                                                          hir::BindByValue(hir::MutMutable));
-                    arm(vec![iter_pat], loop_expr)
-                };
+                    // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
+                    let into_iter_expr = {
+                        let into_iter_path = {
+                            let strs = std_path(lctx, &["iter", "IntoIterator", "into_iter"]);
 
-                // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
-                let into_iter_expr = {
-                    let into_iter_path = {
-                        let strs = std_path(lctx, &["iter", "IntoIterator", "into_iter"]);
+                            path_global(e.span, strs)
+                        };
 
-                        path_global(e.span, strs)
+                        let into_iter = expr_path(lctx, into_iter_path);
+                        expr_call(lctx, e.span, into_iter, vec![head])
                     };
 
-                    expr_call(lctx, e.span, expr_path(lctx, into_iter_path), vec![head])
-                };
-
-                let match_expr = expr_match(lctx,
-                                            e.span,
-                                            into_iter_expr,
-                                            vec![iter_arm],
-                                            hir::MatchSource::ForLoopDesugar);
-
-                // `{ let result = ...; result }`
-                let result_ident = lctx.str_to_ident("result");
-                return expr_block(lctx,
-                                  block_all(lctx,
-                                            e.span,
-                                            vec![stmt_let(lctx,
-                                                          e.span,
-                                                          false,
-                                                          result_ident,
-                                                          match_expr)],
-                                            Some(expr_ident(lctx, e.span, result_ident))));
+                    let match_expr = expr_match(lctx,
+                                                e.span,
+                                                into_iter_expr,
+                                                vec![iter_arm],
+                                                hir::MatchSource::ForLoopDesugar);
+
+                    // `{ let result = ...; result }`
+                    let result_ident = lctx.str_to_ident("result");
+                    let let_stmt = stmt_let(lctx, e.span, false, result_ident, match_expr);
+                    let result = expr_ident(lctx, e.span, result_ident);
+                    let block = block_all(lctx, e.span, vec![let_stmt], Some(result));
+                    expr_block(lctx, block)
+                });
             }
 
             ExprMac(_) => panic!("Shouldn't exist here"),