]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/stmt.rs
Convert Drop statement into terminator
[rust.git] / src / librustc_mir / build / stmt.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use build::{BlockAnd, BlockAndExtension, Builder};
12 use hair::*;
13 use rustc::mir::repr::*;
14
15 impl<'a,'tcx> Builder<'a,'tcx> {
16     pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec<StmtRef<'tcx>>) -> BlockAnd<()> {
17         // This convoluted structure is to avoid using recursion as we walk down a list
18         // of statements. Basically, the structure we get back is something like:
19         //
20         //    let x = <init> in {
21         //       let y = <init> in {
22         //           expr1;
23         //           expr2;
24         //       }
25         //    }
26         //
27         // To process this, we keep a stack of (Option<CodeExtent>,
28         // vec::IntoIter<Stmt>) pairs.  At each point we pull off the
29         // top most pair and extract one statement from the
30         // iterator. Once it's complete, we pop the scope from the
31         // first half the pair.
32         let this = self;
33         let mut stmt_lists = vec![(None, stmts.into_iter())];
34         while !stmt_lists.is_empty() {
35             let stmt = {
36                 let &mut (_, ref mut stmts) = stmt_lists.last_mut().unwrap();
37                 stmts.next()
38             };
39
40             let stmt = match stmt {
41                 Some(stmt) => stmt,
42                 None => {
43                     let (extent, _) = stmt_lists.pop().unwrap();
44                     if let Some(extent) = extent {
45                         unpack!(block = this.pop_scope(extent, block));
46                     }
47                     continue
48                 }
49             };
50
51             let Stmt { span: _, kind } = this.hir.mirror(stmt);
52             match kind {
53                 StmtKind::Let { remainder_scope, init_scope, pattern, initializer, stmts } => {
54                     this.push_scope(remainder_scope);
55                     stmt_lists.push((Some(remainder_scope), stmts.into_iter()));
56                     unpack!(block = this.in_scope(init_scope, block, move |this| {
57                         // FIXME #30046                              ^~~~
58                         match initializer {
59                             Some(initializer) => {
60                                 this.expr_into_pattern(block, remainder_scope, pattern, initializer)
61                             }
62                             None => {
63                                 this.declare_bindings(remainder_scope, &pattern);
64                                 block.unit()
65                             }
66                         }
67                     }));
68                 }
69
70                 StmtKind::Expr { scope, expr } => {
71                     unpack!(block = this.in_scope(scope, block, |this| {
72                         let expr = this.hir.mirror(expr);
73                         let temp = this.temp(expr.ty.clone());
74                         unpack!(block = this.into(&temp, block, expr));
75                         unpack!(block = this.build_drop(block, temp));
76                         block.unit()
77                     }));
78                 }
79             }
80         }
81         block.unit()
82     }
83 }