]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_mir/build/expr/into.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_mir / build / expr / into.rs
index ca00b99b108987b2aa57f8e2d95c49ddeccc115b..231d7da10a02dc53ad2e8615f6a5b0e388167e93 100644 (file)
@@ -15,7 +15,7 @@ use build::expr::category::{Category, RvalueFunc};
 use build::scope::LoopScope;
 use hair::*;
 use rustc::middle::region::CodeExtent;
-use rustc::middle::ty;
+use rustc::ty;
 use rustc::mir::repr::*;
 use syntax::codemap::Span;
 
@@ -36,10 +36,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         // just use the name `this` uniformly
         let this = self;
         let expr_span = expr.span;
+        let scope_id = this.innermost_scope_id();
 
         match expr.kind {
             ExprKind::Scope { extent, value } => {
-                this.in_scope(extent, block, |this| this.into(destination, block, value))
+                this.in_scope(extent, block, |this, _| this.into(destination, block, value))
             }
             ExprKind::Block { body: ast_block } => {
                 this.ast_block(destination, block, ast_block)
@@ -52,7 +53,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
 
                 let mut then_block = this.cfg.start_new_block();
                 let mut else_block = this.cfg.start_new_block();
-                this.cfg.terminate(block, Terminator::If {
+                this.cfg.terminate(block, scope_id, expr_span, TerminatorKind::If {
                     cond: operand,
                     targets: (then_block, else_block)
                 });
@@ -63,13 +64,20 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 } else {
                     // Body of the `if` expression without an `else` clause must return `()`, thus
                     // we implicitly generate a `else {}` if it is not specified.
-                    this.cfg.push_assign_unit(else_block, expr_span, destination);
+                    let scope_id = this.innermost_scope_id();
+                    this.cfg.push_assign_unit(else_block, scope_id, expr_span, destination);
                     else_block
                 };
 
                 let join_block = this.cfg.start_new_block();
-                this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
-                this.cfg.terminate(else_block, Terminator::Goto { target: join_block });
+                this.cfg.terminate(then_block,
+                                   scope_id,
+                                   expr_span,
+                                   TerminatorKind::Goto { target: join_block });
+                this.cfg.terminate(else_block,
+                                   scope_id,
+                                   expr_span,
+                                   TerminatorKind::Goto { target: join_block });
 
                 join_block.unit()
             }
@@ -95,16 +103,19 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                     LogicalOp::And => (else_block, false_block),
                     LogicalOp::Or => (true_block, else_block),
                 };
-                this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });
+                this.cfg.terminate(block,
+                                   scope_id,
+                                   expr_span,
+                                   TerminatorKind::If { cond: lhs, targets: blocks });
 
                 let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
-                this.cfg.terminate(else_block, Terminator::If {
+                this.cfg.terminate(else_block, scope_id, expr_span, TerminatorKind::If {
                     cond: rhs,
                     targets: (true_block, false_block)
                 });
 
                 this.cfg.push_assign_constant(
-                    true_block, expr_span, destination,
+                    true_block, scope_id, expr_span, destination,
                     Constant {
                         span: expr_span,
                         ty: this.hir.bool_ty(),
@@ -112,15 +123,21 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                     });
 
                 this.cfg.push_assign_constant(
-                    false_block, expr_span, destination,
+                    false_block, scope_id, expr_span, destination,
                     Constant {
                         span: expr_span,
                         ty: this.hir.bool_ty(),
                         literal: this.hir.false_literal(),
                     });
 
-                this.cfg.terminate(true_block, Terminator::Goto { target: join_block });
-                this.cfg.terminate(false_block, Terminator::Goto { target: join_block });
+                this.cfg.terminate(true_block,
+                                   scope_id,
+                                   expr_span,
+                                   TerminatorKind::Goto { target: join_block });
+                this.cfg.terminate(false_block,
+                                   scope_id,
+                                   expr_span,
+                                   TerminatorKind::Goto { target: join_block });
 
                 join_block.unit()
             }
@@ -144,7 +161,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 let exit_block = this.cfg.start_new_block();
 
                 // start the loop
-                this.cfg.terminate(block, Terminator::Goto { target: loop_block });
+                this.cfg.terminate(block,
+                                   scope_id,
+                                   expr_span,
+                                   TerminatorKind::Goto { target: loop_block });
 
                 let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
                     // conduct the test, if necessary
@@ -157,7 +177,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                         let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
                         body_block = this.cfg.start_new_block();
                         this.cfg.terminate(loop_block_end,
-                                           Terminator::If {
+                                           scope_id,
+                                           expr_span,
+                                           TerminatorKind::If {
                                                cond: cond,
                                                targets: (body_block, exit_block)
                                            });
@@ -173,12 +195,15 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                     let tmp = this.get_unit_temp();
                     // Execute the body, branching back to the test.
                     let body_block_end = unpack!(this.into(&tmp, body_block, body));
-                    this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
+                    this.cfg.terminate(body_block_end,
+                                       scope_id,
+                                       expr_span,
+                                       TerminatorKind::Goto { target: loop_block });
                 });
                 // If the loop may reach its exit_block, we assign an empty tuple to the
                 // destination to keep the MIR well-formed.
                 if might_break {
-                    this.cfg.push_assign_unit(exit_block, expr_span, destination);
+                    this.cfg.push_assign_unit(exit_block, scope_id, expr_span, destination);
                 }
                 exit_block.unit()
             }
@@ -186,10 +211,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 // Note: we evaluate assignments right-to-left. This
                 // is better for borrowck interaction with overloaded
                 // operators like x[j] = x[i].
+                let lhs = this.hir.mirror(lhs);
+                let lhs_span = lhs.span;
                 let rhs = unpack!(block = this.as_operand(block, rhs));
                 let lhs = unpack!(block = this.as_lvalue(block, lhs));
-                unpack!(block = this.build_drop(block, lhs.clone()));
-                this.cfg.push_assign(block, expr_span, &lhs, Rvalue::Use(rhs));
+                unpack!(block = this.build_drop(block, lhs_span, lhs.clone()));
+                this.cfg.push_assign(block, scope_id, expr_span, &lhs, Rvalue::Use(rhs));
                 block.unit()
             }
             ExprKind::AssignOp { op, lhs, rhs } => {
@@ -208,7 +235,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 // we don't have to drop prior contents or anything
                 // because AssignOp is only legal for Copy types
                 // (overloaded ops should be desugared into a call).
-                this.cfg.push_assign(block, expr_span, &lhs,
+                this.cfg.push_assign(block, scope_id, expr_span, &lhs,
                                      Rvalue::BinaryOp(op,
                                                       Operand::Consume(lhs.clone()),
                                                       rhs));
@@ -229,17 +256,20 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 block = match value {
                     Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
                     None => {
-                        this.cfg.push_assign_unit(block, expr_span, &Lvalue::ReturnPointer);
+                        this.cfg.push_assign_unit(block, scope_id,
+                                                  expr_span, &Lvalue::ReturnPointer);
                         block
                     }
                 };
-                let extent = this.extent_of_outermost_scope();
+                let extent = this.extent_of_return_scope();
                 this.exit_scope(expr_span, extent, block, END_BLOCK);
                 this.cfg.start_new_block().unit()
             }
             ExprKind::Call { ty, fun, args } => {
                 let diverges = match ty.sty {
-                    ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
+                    ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => {
+                        f.sig.0.output.diverges()
+                    }
                     _ => false
                 };
                 let fun = unpack!(block = this.as_operand(block, fun));
@@ -250,7 +280,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
 
                 let success = this.cfg.start_new_block();
                 let cleanup = this.diverge_cleanup();
-                this.cfg.terminate(block, Terminator::Call {
+                this.cfg.terminate(block, scope_id, expr_span, TerminatorKind::Call {
                     func: fun,
                     args: args,
                     cleanup: cleanup,
@@ -291,7 +321,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 });
 
                 let rvalue = unpack!(block = this.as_rvalue(block, expr));
-                this.cfg.push_assign(block, expr_span, destination, rvalue);
+                this.cfg.push_assign(block, scope_id, expr_span, destination, rvalue);
                 block.unit()
             }
         }