@@ -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,51 @@ 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
+ self . pop_scope ( extent, block) ;
139
+ debug ! ( "in_scope: exiting extent={:?} block={:?}" , extent, block) ;
140
+ block. and ( rv)
141
+ }
137
142
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) ;
139
149
140
150
// push scope, execute `f`, then pop scope again
141
151
self . scopes . push ( Scope {
142
152
extent : extent. clone ( ) ,
143
153
drops : vec ! [ ] ,
144
- exits : vec ! [ ] ,
145
154
cached_block : None ,
146
155
} ) ;
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) ;
149
166
150
167
// add in any drops needed on the fallthrough path (any other
151
168
// exiting paths, such as those that arise from `break`, will
152
169
// have drops already)
153
170
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) ;
155
172
}
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
173
}
169
174
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
175
186
176
/// Finds the loop scope for a given label. This is used for
187
177
/// resolving `break` and `continue`.
@@ -232,8 +222,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
232
222
for & ( kind, drop_span, ref lvalue) in & scope. drops {
233
223
self . cfg . push_drop ( block, drop_span, kind, lvalue) ;
234
224
}
235
-
236
- scope. exits . push ( self . cfg . end_point ( block) ) ;
237
225
}
238
226
239
227
self . cfg . terminate ( block, Terminator :: Goto { target : target } ) ;
@@ -272,12 +260,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
272
260
}
273
261
}
274
262
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 ( )
277
265
}
278
266
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 ( )
281
269
}
282
270
}
283
271
0 commit comments