@@ -14,48 +14,70 @@ use repr::*;
1414
1515impl < ' a , ' tcx > Builder < ' a , ' tcx > {
1616 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.
2432 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+ }
3567 } ) ) ;
36- this. stmts ( block, stmts)
37- } )
38- }
68+ }
3969
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) ;
4476 block. unit( )
4577 } ) ) ;
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+ }
5879 }
5980 }
81+ block. unit ( )
6082 }
6183}
0 commit comments