@@ -155,8 +155,10 @@ struct BreakableScope<'tcx> {
155155 /// The destination of the loop/block expression itself (i.e., where to put
156156 /// the result of a `break` or `return` expression)
157157 break_destination : Place < ' tcx > ,
158- /// Drops that happen on the
159- drops : DropTree ,
158+ /// Drops that happen on the `break`/`return` path.
159+ break_drops : DropTree ,
160+ /// Drops that happen on the `continue` path.
161+ continue_drops : Option < DropTree > ,
160162}
161163
162164/// The target of an expression that breaks out of a scope
@@ -172,10 +174,8 @@ rustc_index::newtype_index! {
172174}
173175
174176const ROOT_NODE : DropIdx = DropIdx :: from_u32_const ( 0 ) ;
175- const CONTINUE_NODE : DropIdx = DropIdx :: from_u32_const ( 1 ) ;
176177
177- /// A tree (usually, sometimes this is a forest of two trees) of drops that we
178- /// have deferred lowering. It's used for:
178+ /// A tree of drops that we have deferred lowering. It's used for:
179179///
180180/// * Drops on unwind paths
181181/// * Drops on generator drop paths (when a suspended generator is dropped)
@@ -189,12 +189,10 @@ struct DropTree {
189189 drops : IndexVec < DropIdx , ( DropData , DropIdx ) > ,
190190 /// Map for finding the inverse of the `next_drop` relation:
191191 ///
192- /// `previous_drops[(next_drop [i], drops[i].local, drops[i].kind] == i`
192+ /// `previous_drops[(drops [i].1 , drops[i].0. local, drops[i].0 .kind] == i`
193193 previous_drops : FxHashMap < ( DropIdx , Local , DropKind ) , DropIdx > ,
194194 /// Edges into the `DropTree` that need to be added once it's lowered.
195195 entry_points : Vec < ( DropIdx , BasicBlock ) > ,
196- /// The first non-root nodes in the forest.
197- first_non_root : DropIdx ,
198196}
199197
200198impl Scope {
@@ -225,15 +223,14 @@ trait DropTreeBuilder<'tcx> {
225223}
226224
227225impl DropTree {
228- fn new ( num_roots : usize ) -> Self {
226+ fn new ( ) -> Self {
229227 let fake_source_info = SourceInfo { span : DUMMY_SP , scope : OUTERMOST_SOURCE_SCOPE } ;
230228 let fake_data =
231229 DropData { source_info : fake_source_info, local : Local :: MAX , kind : DropKind :: Storage } ;
232230 let drop_idx = DropIdx :: MAX ;
233- let drops = IndexVec :: from_elem_n ( ( fake_data, drop_idx) , num_roots ) ;
231+ let drops = IndexVec :: from_elem_n ( ( fake_data, drop_idx) , 1 ) ;
234232 Self {
235233 drops,
236- first_non_root : DropIdx :: from_usize ( num_roots) ,
237234 entry_points : Vec :: new ( ) ,
238235 previous_drops : FxHashMap :: default ( ) ,
239236 }
@@ -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 ,
@@ -347,7 +347,7 @@ impl DropTree {
347347 cfg. terminate ( block, drop_data. 0 . source_info , terminator) ;
348348 }
349349 // Root nodes don't correspond to a drop.
350- DropKind :: Storage if drop_idx < self . first_non_root => { }
350+ DropKind :: Storage if drop_idx == ROOT_NODE => { }
351351 DropKind :: Storage => {
352352 let stmt = Statement {
353353 source_info : drop_data. 0 . source_info ,
@@ -366,12 +366,12 @@ impl DropTree {
366366}
367367
368368impl < ' tcx > Scopes < ' tcx > {
369- pub ( crate ) fn new ( is_generator : bool ) -> Self {
369+ pub ( crate ) fn new ( ) -> Self {
370370 Self {
371371 scopes : Vec :: new ( ) ,
372372 breakable_scopes : Vec :: new ( ) ,
373- unwind_drops : DropTree :: new ( 1 ) ,
374- generator_drops : DropTree :: new ( is_generator as usize ) ,
373+ unwind_drops : DropTree :: new ( ) ,
374+ generator_drops : DropTree :: new ( ) ,
375375 }
376376 }
377377
@@ -429,13 +429,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
429429 let scope = BreakableScope {
430430 region_scope,
431431 break_destination,
432- drops : DropTree :: new ( 1 + loop_block. is_some ( ) as usize ) ,
432+ break_drops : DropTree :: new ( ) ,
433+ continue_drops : loop_block. map ( |_| DropTree :: new ( ) ) ,
433434 } ;
434435 self . scopes . breakable_scopes . push ( scope) ;
435436 let normal_exit_block = f ( self ) ;
436437 let breakable_scope = self . scopes . breakable_scopes . pop ( ) . unwrap ( ) ;
437438 assert ! ( breakable_scope. region_scope == region_scope) ;
438- let break_block = self . build_exit_tree ( breakable_scope. drops , loop_block) ;
439+ let break_block = self . build_exit_tree ( breakable_scope. break_drops , None ) ;
440+ breakable_scope. continue_drops . map ( |drops| {
441+ self . build_exit_tree ( drops, loop_block) ;
442+ } ) ;
439443 match ( normal_exit_block, break_block) {
440444 ( Some ( block) , None ) | ( None , Some ( block) ) => block,
441445 ( None , None ) => self . cfg . start_new_block ( ) . unit ( ) ,
@@ -600,10 +604,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
600604
601605 let region_scope = self . scopes . breakable_scopes [ break_index] . region_scope ;
602606 let scope_index = self . scopes . scope_index ( region_scope, span) ;
603- let exited_scopes = & self . scopes . scopes [ scope_index + 1 ..] ;
604- let scope_drops = exited_scopes. iter ( ) . flat_map ( |scope| & scope. drops ) ;
607+ let drops = if destination. is_some ( ) {
608+ & mut self . scopes . breakable_scopes [ break_index] . break_drops
609+ } else {
610+ self . scopes . breakable_scopes [ break_index] . continue_drops . as_mut ( ) . unwrap ( )
611+ } ;
605612
606- let drops = & mut self . scopes . breakable_scopes [ break_index] . drops ;
607613 let mut drop_idx = DropIdx :: from_u32 ( destination. is_none ( ) as u32 ) ;
608614 for drop in scope_drops {
609615 drop_idx = drops. add_drop ( * drop, drop_idx) ;
@@ -1095,15 +1101,13 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
10951101 continue_block : Option < BasicBlock > ,
10961102 ) -> Option < BlockAnd < ( ) > > {
10971103 let mut blocks = IndexVec :: from_elem ( None , & drops. drops ) ;
1098- if continue_block. is_some ( ) {
1099- blocks[ CONTINUE_NODE ] = continue_block;
1100- }
1104+ blocks[ ROOT_NODE ] = continue_block;
1105+
11011106 drops. build_mir :: < ExitScopes > ( & mut self . cfg , & mut blocks) ;
11021107 if drops. drops . iter ( ) . any ( |( drop, _) | drop. kind == DropKind :: Value ) {
11031108 let unwind_target = self . diverge_cleanup ( ) ;
1104- let num_roots = drops. first_non_root . index ( ) ;
1105- let mut unwind_indices = IndexVec :: from_elem_n ( unwind_target, num_roots) ;
1106- for ( drop_idx, drop_data) in drops. drops . iter_enumerated ( ) . skip ( num_roots) {
1109+ let mut unwind_indices = IndexVec :: from_elem_n ( unwind_target, 1 ) ;
1110+ for ( drop_idx, drop_data) in drops. drops . iter_enumerated ( ) . skip ( 1 ) {
11071111 match drop_data. 0 . kind {
11081112 DropKind :: Storage => {
11091113 if self . is_generator {
0 commit comments