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.
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.
11 use build
::{BlockAnd, BlockAndExtension, Builder}
;
13 use rustc
::mir
::repr
::*;
16 impl<'a
,'tcx
> Builder
<'a
,'tcx
> {
17 pub fn ast_block(&mut self,
18 destination
: &Lvalue
<'tcx
>,
19 mut block
: BasicBlock
,
20 ast_block
: &'tcx hir
::Block
)
22 let Block { extent, span, stmts, expr }
= self.hir
.mirror(ast_block
);
23 self.in_scope(extent
, block
, move |this
, _
| {
24 // This convoluted structure is to avoid using recursion as we walk down a list
25 // of statements. Basically, the structure we get back is something like:
27 // let x = <init> in {
29 // let y = <init> in {
36 // The let bindings are valid till the end of block so all we have to do is to pop all
37 // the let-scopes at the end.
39 // First we build all the statements in the block.
40 let mut let_extent_stack
= Vec
::with_capacity(8);
42 let Stmt { span: _, kind }
= this
.hir
.mirror(stmt
);
44 StmtKind
::Expr { scope, expr }
=> {
45 unpack
!(block
= this
.in_scope(scope
, block
, |this
, _
| {
46 let expr
= this
.hir
.mirror(expr
);
47 let expr_span
= expr
.span
;
48 let temp
= this
.temp(expr
.ty
.clone());
49 unpack
!(block
= this
.into(&temp
, block
, expr
));
50 unpack
!(block
= this
.build_drop(block
, expr_span
, temp
));
54 StmtKind
::Let { remainder_scope, init_scope, pattern, initializer }
=> {
55 let remainder_scope_id
= this
.push_scope(remainder_scope
, block
);
56 let_extent_stack
.push(remainder_scope
);
57 unpack
!(block
= this
.in_scope(init_scope
, block
, move |this
, _
| {
59 if let Some(init
) = initializer
{
60 this
.expr_into_pattern(block
, remainder_scope_id
, pattern
, init
)
62 this
.declare_bindings(remainder_scope_id
, &pattern
);
69 // Then, the block may have an optional trailing expression which is a “return” value
71 if let Some(expr
) = expr
{
72 unpack
!(block
= this
.into(destination
, block
, expr
));
75 let scope_id
= this
.innermost_scope_id();
76 this
.cfg
.push_assign_unit(block
, scope_id
, span
, destination
);
78 // Finally, we pop all the let scopes before exiting out from the scope of block
80 for extent
in let_extent_stack
.into_iter().rev() {
81 unpack
!(block
= this
.pop_scope(extent
, block
));