]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/build/block.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / librustc_mir / build / block.rs
CommitLineData
e9174d1e
SL
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
9cc50fc6 11use build::{BlockAnd, BlockAndExtension, Builder};
e9174d1e 12use hair::*;
c30ab7b3 13use rustc::mir::*;
54a0048b 14use rustc::hir;
e9174d1e 15
a7813a04 16impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
e9174d1e 17 pub fn ast_block(&mut self,
b039eaaf 18 destination: &Lvalue<'tcx>,
a7813a04
XL
19 // FIXME(#32959): temporary measure for the issue
20 dest_is_unit: bool,
e9174d1e 21 mut block: BasicBlock,
b039eaaf 22 ast_block: &'tcx hir::Block)
e9174d1e 23 -> BlockAnd<()> {
9cc50fc6 24 let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
3157f602 25 self.in_scope(extent, block, move |this| {
54a0048b
SL
26 // This convoluted structure is to avoid using recursion as we walk down a list
27 // of statements. Basically, the structure we get back is something like:
28 //
29 // let x = <init> in {
30 // expr1;
31 // let y = <init> in {
32 // expr2;
33 // expr3;
34 // ...
35 // }
36 // }
37 //
38 // The let bindings are valid till the end of block so all we have to do is to pop all
39 // the let-scopes at the end.
40 //
41 // First we build all the statements in the block.
42 let mut let_extent_stack = Vec::with_capacity(8);
3157f602 43 let outer_visibility_scope = this.visibility_scope;
54a0048b
SL
44 for stmt in stmts {
45 let Stmt { span: _, kind } = this.hir.mirror(stmt);
46 match kind {
47 StmtKind::Expr { scope, expr } => {
3157f602 48 unpack!(block = this.in_scope(scope, block, |this| {
54a0048b 49 let expr = this.hir.mirror(expr);
a7813a04 50 this.stmt_expr(block, expr)
54a0048b
SL
51 }));
52 }
53 StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
3157f602
XL
54 let tcx = this.hir.tcx();
55
56 // Enter the remainder scope, i.e. the bindings' destruction scope.
57 this.push_scope(remainder_scope, block);
54a0048b 58 let_extent_stack.push(remainder_scope);
3157f602
XL
59
60 // Declare the bindings, which may create a visibility scope.
61 let remainder_span = remainder_scope.span(&tcx.region_maps, &tcx.map);
62 let remainder_span = remainder_span.unwrap_or(span);
63 let scope = this.declare_bindings(None, remainder_span, &pattern);
64
65 // Evaluate the initializer, if present.
66 if let Some(init) = initializer {
67 unpack!(block = this.in_scope(init_scope, block, move |this| {
68 // FIXME #30046 ^~~~
69 this.expr_into_pattern(block, pattern, init)
70 }));
5bcae85e
SL
71 } else {
72 this.storage_live_for_bindings(block, &pattern);
3157f602
XL
73 }
74
75 // Enter the visibility scope, after evaluating the initializer.
76 if let Some(visibility_scope) = scope {
77 this.visibility_scope = visibility_scope;
78 }
54a0048b 79 }
9cc50fc6
SL
80 }
81 }
54a0048b
SL
82 // Then, the block may have an optional trailing expression which is a “return” value
83 // of the block.
84 if let Some(expr) = expr {
85 unpack!(block = this.into(destination, block, expr));
a7813a04 86 } else if dest_is_unit {
54a0048b 87 // FIXME(#31472)
3157f602
XL
88 let source_info = this.source_info(span);
89 this.cfg.push_assign_unit(block, source_info, destination);
54a0048b
SL
90 }
91 // Finally, we pop all the let scopes before exiting out from the scope of block
92 // itself.
93 for extent in let_extent_stack.into_iter().rev() {
94 unpack!(block = this.pop_scope(extent, block));
95 }
3157f602
XL
96 // Restore the original visibility scope.
97 this.visibility_scope = outer_visibility_scope;
54a0048b 98 block.unit()
e9174d1e
SL
99 })
100 }
101}