@@ -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,50 @@ 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+ assert_eq ! ( self . extent_of_innermost_scope( ) , extent) ;
139+ self . pop_scope ( block) ;
140+ debug ! ( "in_scope: exiting extent={:?} block={:?}" , extent, block) ;
141+ block. and ( rv)
142+ }
137143
138- let start_point = self . cfg . end_point ( block) ;
144+ /// Push a scope onto the stack. You can then build code in this
145+ /// scope and call `pop_scope` afterwards. Note that these two
146+ /// calls must be paired; using `in_scope` as a convenience
147+ /// wrapper maybe preferable.
148+ pub fn push_scope ( & mut self , extent : CodeExtent , block : BasicBlock ) {
149+ debug ! ( "push_scope({:?}, {:?})" , extent, block) ;
139150
140151 // push scope, execute `f`, then pop scope again
141152 self . scopes . push ( Scope {
142153 extent : extent. clone ( ) ,
143154 drops : vec ! [ ] ,
144- exits : vec ! [ ] ,
145155 cached_block : None ,
146156 } ) ;
147- let BlockAnd ( fallthrough_block, rv) = f ( self ) ;
148- let mut scope = self . scopes . pop ( ) . unwrap ( ) ;
157+ }
158+
159+ /// Pops the innermost scope, adding any drops onto the end of
160+ /// `block` that are needed. This must match 1-to-1 with
161+ /// `push_scope`.
162+ pub fn pop_scope ( & mut self , block : BasicBlock ) {
163+ debug ! ( "pop_scope({:?})" , block) ;
164+ let scope = self . scopes . pop ( ) . unwrap ( ) ;
149165
150166 // add in any drops needed on the fallthrough path (any other
151167 // exiting paths, such as those that arise from `break`, will
152168 // have drops already)
153169 for ( kind, span, lvalue) in scope. drops {
154- self . cfg . push_drop ( fallthrough_block , span, kind, & lvalue) ;
170+ self . cfg . push_drop ( block , span, kind, & lvalue) ;
155171 }
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)
168172 }
169173
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- }
185174
186175 /// Finds the loop scope for a given label. This is used for
187176 /// resolving `break` and `continue`.
@@ -232,8 +221,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
232221 for & ( kind, drop_span, ref lvalue) in & scope. drops {
233222 self . cfg . push_drop ( block, drop_span, kind, lvalue) ;
234223 }
235-
236- scope. exits . push ( self . cfg . end_point ( block) ) ;
237224 }
238225
239226 self . cfg . terminate ( block, Terminator :: Goto { target : target } ) ;
@@ -272,12 +259,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
272259 }
273260 }
274261
275- pub fn extent_of_innermost_scope ( & self ) -> Option < CodeExtent > {
276- self . scopes . last ( ) . map ( |scope| scope. extent )
262+ pub fn extent_of_innermost_scope ( & self ) -> CodeExtent {
263+ self . scopes . last ( ) . map ( |scope| scope. extent ) . unwrap ( )
277264 }
278265
279- pub fn extent_of_outermost_scope ( & self ) -> Option < CodeExtent > {
280- self . scopes . first ( ) . map ( |scope| scope. extent )
266+ pub fn extent_of_outermost_scope ( & self ) -> CodeExtent {
267+ self . scopes . first ( ) . map ( |scope| scope. extent ) . unwrap ( )
281268 }
282269}
283270
0 commit comments