@@ -94,7 +94,6 @@ use syntax::codemap::Span;
94
94
95
95
pub struct Scope < ' tcx > {
96
96
extent : CodeExtent ,
97
- exits : Vec < ExecutionPoint > ,
98
97
drops : Vec < ( DropKind , Span , Lvalue < ' tcx > ) > ,
99
98
cached_block : Option < BasicBlock > ,
100
99
}
@@ -116,7 +115,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
116
115
-> BlockAnd < R >
117
116
where F : FnOnce ( & mut Builder < ' a , ' tcx > ) -> BlockAnd < R >
118
117
{
119
- let extent = self . extent_of_innermost_scope ( ) . unwrap ( ) ;
118
+ let extent = self . extent_of_innermost_scope ( ) ;
120
119
let loop_scope = LoopScope {
121
120
extent : extent. clone ( ) ,
122
121
continue_block : loop_block,
@@ -128,60 +127,50 @@ impl<'a,'tcx> Builder<'a,'tcx> {
128
127
r
129
128
}
130
129
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 >
134
133
where F : FnOnce ( & mut Builder < ' a , ' tcx > ) -> BlockAnd < R >
135
134
{
136
135
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
+ }
137
143
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) ;
139
150
140
151
// push scope, execute `f`, then pop scope again
141
152
self . scopes . push ( Scope {
142
153
extent : extent. clone ( ) ,
143
154
drops : vec ! [ ] ,
144
- exits : vec ! [ ] ,
145
155
cached_block : None ,
146
156
} ) ;
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 ( ) ;
149
165
150
166
// add in any drops needed on the fallthrough path (any other
151
167
// exiting paths, such as those that arise from `break`, will
152
168
// have drops already)
153
169
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) ;
155
171
}
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)
168
172
}
169
173
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
- }
185
174
186
175
/// Finds the loop scope for a given label. This is used for
187
176
/// resolving `break` and `continue`.
@@ -232,8 +221,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
232
221
for & ( kind, drop_span, ref lvalue) in & scope. drops {
233
222
self . cfg . push_drop ( block, drop_span, kind, lvalue) ;
234
223
}
235
-
236
- scope. exits . push ( self . cfg . end_point ( block) ) ;
237
224
}
238
225
239
226
self . cfg . terminate ( block, Terminator :: Goto { target : target } ) ;
@@ -272,12 +259,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
272
259
}
273
260
}
274
261
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 ( )
277
264
}
278
265
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 ( )
281
268
}
282
269
}
283
270
0 commit comments