@@ -94,7 +94,6 @@ use syntax::codemap::Span;
9494
9595pub struct Scope < ' tcx > {
9696 extent : CodeExtent ,
97- exits : Vec < ExecutionPoint > ,
9897 drops : Vec < ( DropKind , Span , Lvalue < ' tcx > ) > ,
9998 cached_block : Option < BasicBlock > ,
10099}
@@ -116,7 +115,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
116115 -> BlockAnd < R >
117116 where F : FnOnce ( & mut Builder < ' a , ' tcx > ) -> BlockAnd < R >
118117 {
119- let extent = self . extent_of_innermost_scope ( ) . unwrap ( ) ;
118+ let extent = self . extent_of_innermost_scope ( ) ;
120119 let loop_scope = LoopScope {
121120 extent : extent. clone ( ) ,
122121 continue_block : loop_block,
@@ -128,60 +127,51 @@ impl<'a,'tcx> Builder<'a,'tcx> {
128127 r
129128 }
130129
131- /// Start a scope. The closure `f` should translate the contents
132- /// of the scope. See module comment for more details .
133- pub fn in_scope < F , R > ( & mut self , extent : CodeExtent , block : BasicBlock , f : F ) -> BlockAnd < R >
130+ /// Convenience wrapper that pushes a scope and then executes `f`
131+ /// to build its contents, popping the scope afterwards .
132+ pub fn in_scope < F , R > ( & mut self , extent : CodeExtent , mut block : BasicBlock , f : F ) -> BlockAnd < R >
134133 where F : FnOnce ( & mut Builder < ' a , ' tcx > ) -> BlockAnd < R >
135134 {
136135 debug ! ( "in_scope(extent={:?}, block={:?})" , extent, block) ;
136+ self . push_scope ( extent, block) ;
137+ let rv = unpack ! ( block = f( self ) ) ;
138+ self . pop_scope ( extent, block) ;
139+ debug ! ( "in_scope: exiting extent={:?} block={:?}" , extent, block) ;
140+ block. and ( rv)
141+ }
137142
138- let start_point = self . cfg . end_point ( block) ;
143+ /// Push a scope onto the stack. You can then build code in this
144+ /// scope and call `pop_scope` afterwards. Note that these two
145+ /// calls must be paired; using `in_scope` as a convenience
146+ /// wrapper maybe preferable.
147+ pub fn push_scope ( & mut self , extent : CodeExtent , block : BasicBlock ) {
148+ debug ! ( "push_scope({:?}, {:?})" , extent, block) ;
139149
140150 // push scope, execute `f`, then pop scope again
141151 self . scopes . push ( Scope {
142152 extent : extent. clone ( ) ,
143153 drops : vec ! [ ] ,
144- exits : vec ! [ ] ,
145154 cached_block : None ,
146155 } ) ;
147- let BlockAnd ( fallthrough_block, rv) = f ( self ) ;
148- let mut scope = self . scopes . pop ( ) . unwrap ( ) ;
156+ }
157+
158+ /// Pops a scope, which should have extent `extent`, adding any
159+ /// drops onto the end of `block` that are needed. This must
160+ /// match 1-to-1 with `push_scope`.
161+ pub fn pop_scope ( & mut self , extent : CodeExtent , block : BasicBlock ) {
162+ debug ! ( "pop_scope({:?}, {:?})" , extent, block) ;
163+ let scope = self . scopes . pop ( ) . unwrap ( ) ;
164+
165+ assert_eq ! ( scope. extent, extent) ;
149166
150167 // add in any drops needed on the fallthrough path (any other
151168 // exiting paths, such as those that arise from `break`, will
152169 // have drops already)
153170 for ( kind, span, lvalue) in scope. drops {
154- self . cfg . push_drop ( fallthrough_block , span, kind, & lvalue) ;
171+ self . cfg . push_drop ( block , span, kind, & lvalue) ;
155172 }
156-
157- // add the implicit fallthrough edge
158- scope. exits . push ( self . cfg . end_point ( fallthrough_block) ) ;
159-
160- // compute the extent from start to finish and store it in the graph
161- let graph_extent = self . graph_extent ( start_point, scope. exits ) ;
162- self . extents . entry ( extent)
163- . or_insert ( vec ! [ ] )
164- . push ( graph_extent) ;
165-
166- debug ! ( "in_scope: exiting extent={:?} fallthrough_block={:?}" , extent, fallthrough_block) ;
167- fallthrough_block. and ( rv)
168173 }
169174
170- /// Creates a graph extent (SEME region) from an entry point and
171- /// exit points.
172- fn graph_extent ( & self , entry : ExecutionPoint , exits : Vec < ExecutionPoint > ) -> GraphExtent {
173- if exits. len ( ) == 1 && entry. block == exits[ 0 ] . block {
174- GraphExtent {
175- entry : entry,
176- exit : GraphExtentExit :: Statement ( exits[ 0 ] . statement ) ,
177- }
178- } else {
179- GraphExtent {
180- entry : entry,
181- exit : GraphExtentExit :: Points ( exits) ,
182- }
183- }
184- }
185175
186176 /// Finds the loop scope for a given label. This is used for
187177 /// resolving `break` and `continue`.
@@ -232,8 +222,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
232222 for & ( kind, drop_span, ref lvalue) in & scope. drops {
233223 self . cfg . push_drop ( block, drop_span, kind, lvalue) ;
234224 }
235-
236- scope. exits . push ( self . cfg . end_point ( block) ) ;
237225 }
238226
239227 self . cfg . terminate ( block, Terminator :: Goto { target : target } ) ;
@@ -272,12 +260,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
272260 }
273261 }
274262
275- pub fn extent_of_innermost_scope ( & self ) -> Option < CodeExtent > {
276- self . scopes . last ( ) . map ( |scope| scope. extent )
263+ pub fn extent_of_innermost_scope ( & self ) -> CodeExtent {
264+ self . scopes . last ( ) . map ( |scope| scope. extent ) . unwrap ( )
277265 }
278266
279- pub fn extent_of_outermost_scope ( & self ) -> Option < CodeExtent > {
280- self . scopes . first ( ) . map ( |scope| scope. extent )
267+ pub fn extent_of_outermost_scope ( & self ) -> CodeExtent {
268+ self . scopes . first ( ) . map ( |scope| scope. extent ) . unwrap ( )
281269 }
282270}
283271
0 commit comments