@@ -153,8 +153,10 @@ struct BreakableScope<'tcx> {
153153 /// The destination of the loop/block expression itself (i.e., where to put
154154 /// the result of a `break` or `return` expression)
155155 break_destination : Place < ' tcx > ,
156- /// Drops that happen on the
157- drops : DropTree ,
156+ /// Drops that happen on the `break`/`return` path.
157+ break_drops : DropTree ,
158+ /// Drops that happen on the `continue` path.
159+ continue_drops : Option < DropTree > ,
158160}
159161
160162/// The target of an expression that breaks out of a scope
@@ -170,10 +172,8 @@ rustc_index::newtype_index! {
170172}
171173
172174const ROOT_NODE : DropIdx = DropIdx :: from_u32_const ( 0 ) ;
173- const CONTINUE_NODE : DropIdx = DropIdx :: from_u32_const ( 1 ) ;
174175
175- /// A tree (usually, sometimes this is a forest of two trees) of drops that we
176- /// have deferred lowering. It's used for:
176+ /// A tree of drops that we have deferred lowering. It's used for:
177177///
178178/// * Drops on unwind paths
179179/// * Drops on generator drop paths (when a suspended generator is dropped)
@@ -187,12 +187,10 @@ struct DropTree {
187187 drops : IndexVec < DropIdx , ( DropData , DropIdx ) > ,
188188 /// Map for finding the inverse of the `next_drop` relation:
189189 ///
190- /// `previous_drops[(next_drop [i], drops[i].local, drops[i].kind] == i`
190+ /// `previous_drops[(drops [i].1 , drops[i].0. local, drops[i].0 .kind] == i`
191191 previous_drops : FxHashMap < ( DropIdx , Local , DropKind ) , DropIdx > ,
192192 /// Edges into the `DropTree` that need to be added once it's lowered.
193193 entry_points : Vec < ( DropIdx , BasicBlock ) > ,
194- /// The first non-root nodes in the forest.
195- first_non_root : DropIdx ,
196194}
197195
198196impl Scope {
@@ -223,18 +221,17 @@ trait DropTreeBuilder<'tcx> {
223221}
224222
225223impl DropTree {
226- fn new ( num_roots : usize ) -> Self {
224+ fn new ( ) -> Self {
227225 let fake_source_info = SourceInfo { span : DUMMY_SP , scope : OUTERMOST_SOURCE_SCOPE } ;
228226 let fake_data = DropData {
229227 source_info : fake_source_info,
230228 local : Local :: MAX ,
231229 kind : DropKind :: Storage ,
232230 } ;
233231 let drop_idx = DropIdx :: MAX ;
234- let drops = IndexVec :: from_elem_n ( ( fake_data, drop_idx) , num_roots ) ;
232+ let drops = IndexVec :: from_elem_n ( ( fake_data, drop_idx) , 1 ) ;
235233 Self {
236234 drops,
237- first_non_root : DropIdx :: from_usize ( num_roots) ,
238235 entry_points : Vec :: new ( ) ,
239236 previous_drops : FxHashMap :: default ( ) ,
240237 }
@@ -248,6 +245,7 @@ impl DropTree {
248245 }
249246
250247 fn add_entry ( & mut self , from : BasicBlock , to : DropIdx ) {
248+ debug_assert ! ( to < self . drops. next_index( ) ) ;
251249 self . entry_points . push ( ( to, from) ) ;
252250 }
253251
@@ -285,9 +283,11 @@ impl DropTree {
285283 }
286284
287285 let mut needs_block = IndexVec :: from_elem ( Block :: None , & self . drops ) ;
288- if self . first_non_root > CONTINUE_NODE {
289- // `continue` already has its own node.
290- needs_block[ CONTINUE_NODE ] = Block :: Own ;
286+ if blocks[ ROOT_NODE ] . is_some ( ) {
287+ // In some cases (such as drops for `continue`) the root node
288+ // already has a block. In this case, make sure that we don't
289+ // override it.
290+ needs_block[ ROOT_NODE ] = Block :: Own ;
291291 }
292292
293293 // Sort so that we only need to check the last
@@ -315,7 +315,7 @@ impl DropTree {
315315 if let DropKind :: Value = drop_data. 0 . kind {
316316 needs_block[ drop_data. 1 ] = Block :: Own ;
317317 } else {
318- if drop_idx >= self . first_non_root {
318+ if drop_idx != ROOT_NODE {
319319 match & mut needs_block[ drop_data. 1 ] {
320320 pred @ Block :: None => * pred = Block :: Shares ( drop_idx) ,
321321 pred @ Block :: Shares ( _) => * pred = Block :: Own ,
@@ -351,7 +351,7 @@ impl DropTree {
351351 ) ;
352352 }
353353 // Root nodes don't correspond to a drop.
354- DropKind :: Storage if drop_idx < self . first_non_root => { }
354+ DropKind :: Storage if drop_idx == ROOT_NODE => { }
355355 DropKind :: Storage => {
356356 let stmt = Statement {
357357 source_info : drop_data. 0 . source_info ,
@@ -370,12 +370,12 @@ impl DropTree {
370370}
371371
372372impl < ' tcx > Scopes < ' tcx > {
373- pub ( crate ) fn new ( is_generator : bool ) -> Self {
373+ pub ( crate ) fn new ( ) -> Self {
374374 Self {
375375 scopes : Vec :: new ( ) ,
376376 breakable_scopes : Vec :: new ( ) ,
377- unwind_drops : DropTree :: new ( 1 ) ,
378- generator_drops : DropTree :: new ( is_generator as usize ) ,
377+ unwind_drops : DropTree :: new ( ) ,
378+ generator_drops : DropTree :: new ( ) ,
379379 }
380380 }
381381
@@ -436,13 +436,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
436436 let scope = BreakableScope {
437437 region_scope,
438438 break_destination,
439- drops : DropTree :: new ( 1 + loop_block. is_some ( ) as usize ) ,
439+ break_drops : DropTree :: new ( ) ,
440+ continue_drops : loop_block. map ( |_| DropTree :: new ( ) ) ,
440441 } ;
441442 self . scopes . breakable_scopes . push ( scope) ;
442443 let normal_exit_block = f ( self ) ;
443444 let breakable_scope = self . scopes . breakable_scopes . pop ( ) . unwrap ( ) ;
444445 assert ! ( breakable_scope. region_scope == region_scope) ;
445- let break_block = self . build_exit_tree ( breakable_scope. drops , loop_block) ;
446+ let break_block = self . build_exit_tree ( breakable_scope. break_drops , None ) ;
447+ breakable_scope. continue_drops . map ( |drops| {
448+ self . build_exit_tree ( drops, loop_block) ;
449+ } ) ;
446450 match ( normal_exit_block, break_block) {
447451 ( Some ( block) , None ) | ( None , Some ( block) ) => block,
448452 ( None , None ) => self . cfg . start_new_block ( ) . unit ( ) ,
@@ -602,10 +606,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
602606
603607 let region_scope = self . scopes . breakable_scopes [ break_index] . region_scope ;
604608 let scope_index = self . scopes . scope_index ( region_scope, span) ;
605- let exited_scopes = & self . scopes . scopes [ scope_index + 1 ..] ;
606- let scope_drops = exited_scopes. iter ( ) . flat_map ( |scope| & scope. drops ) ;
609+ let drops = if destination. is_some ( ) {
610+ & mut self . scopes . breakable_scopes [ break_index] . break_drops
611+ } else {
612+ self . scopes . breakable_scopes [ break_index] . continue_drops . as_mut ( ) . unwrap ( )
613+ } ;
607614
608- let drops = & mut self . scopes . breakable_scopes [ break_index] . drops ;
609615 let mut drop_idx = DropIdx :: from_u32 ( destination. is_none ( ) as u32 ) ;
610616 for drop in scope_drops {
611617 drop_idx = drops. add_drop ( * drop, drop_idx) ;
@@ -1103,15 +1109,13 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
11031109 continue_block : Option < BasicBlock > ,
11041110 ) -> Option < BlockAnd < ( ) > > {
11051111 let mut blocks = IndexVec :: from_elem ( None , & drops. drops ) ;
1106- if continue_block. is_some ( ) {
1107- blocks[ CONTINUE_NODE ] = continue_block;
1108- }
1112+ blocks[ ROOT_NODE ] = continue_block;
1113+
11091114 drops. build_mir :: < ExitScopes > ( & mut self . cfg , & mut blocks) ;
11101115 if drops. drops . iter ( ) . any ( |( drop, _) | drop. kind == DropKind :: Value ) {
11111116 let unwind_target = self . diverge_cleanup ( ) ;
1112- let num_roots = drops. first_non_root . index ( ) ;
1113- let mut unwind_indices = IndexVec :: from_elem_n ( unwind_target, num_roots) ;
1114- for ( drop_idx, drop_data) in drops. drops . iter_enumerated ( ) . skip ( num_roots) {
1117+ let mut unwind_indices = IndexVec :: from_elem_n ( unwind_target, 1 ) ;
1118+ for ( drop_idx, drop_data) in drops. drops . iter_enumerated ( ) . skip ( 1 ) {
11151119 match drop_data. 0 . kind {
11161120 DropKind :: Storage => {
11171121 if self . is_generator {
0 commit comments