@@ -14,48 +14,70 @@ use repr::*;
14
14
15
15
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
16
16
pub fn stmts ( & mut self , mut block : BasicBlock , stmts : Vec < StmtRef < ' tcx > > ) -> BlockAnd < ( ) > {
17
- for stmt in stmts {
18
- unpack ! ( block = self . stmt( block, stmt) ) ;
19
- }
20
- block. unit ( )
21
- }
22
-
23
- pub fn stmt ( & mut self , mut block : BasicBlock , stmt : 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.
24
32
let this = self ;
25
- let Stmt { span, kind } = this. hir . mirror ( stmt) ;
26
- match kind {
27
- StmtKind :: Let { remainder_scope,
28
- init_scope,
29
- pattern,
30
- initializer : Some ( initializer) ,
31
- stmts } => {
32
- this. in_scope ( remainder_scope, block, |this| {
33
- unpack ! ( block = this. in_scope( init_scope, block, |this| {
34
- this. expr_into_pattern( block, remainder_scope, pattern, initializer)
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
+ 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, block) ;
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
+ }
35
67
} ) ) ;
36
- this. stmts ( block, stmts)
37
- } )
38
- }
68
+ }
39
69
40
- StmtKind :: Let { remainder_scope, init_scope, pattern, initializer : None , stmts } => {
41
- this. in_scope ( remainder_scope, block, |this| {
42
- unpack ! ( block = this. in_scope( init_scope, block, |this| {
43
- this. declare_bindings( remainder_scope, & pattern) ;
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
+ this. cfg. push_drop( block, span, DropKind :: Deep , & temp) ;
44
76
block. unit( )
45
77
} ) ) ;
46
- this. stmts ( block, stmts)
47
- } )
48
- }
49
-
50
- StmtKind :: Expr { scope, expr } => {
51
- this. in_scope ( scope, block, |this| {
52
- let expr = this. hir . mirror ( expr) ;
53
- let temp = this. temp ( expr. ty . clone ( ) ) ;
54
- unpack ! ( block = this. into( & temp, block, expr) ) ;
55
- this. cfg . push_drop ( block, span, DropKind :: Deep , & temp) ;
56
- block. unit ( )
57
- } )
78
+ }
58
79
}
59
80
}
81
+ block. unit ( )
60
82
}
61
83
}
0 commit comments