@@ -209,6 +209,45 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
209209 self . drop_ranges . add_control_edge ( self . expr_index + 1 , self . expr_index + 1 ) ;
210210 }
211211 }
212+
213+ /// Break and continue expression targets might be another expression or a block,
214+ /// but this analysis only looks at expressions. In case a break has a block as a
215+ /// target, this will find the last expression in the block and return its HirId
216+ /// instead.
217+ fn find_target_expression ( & self , hir_id : HirId ) -> HirId {
218+ let node = self . hir . get ( hir_id) ;
219+ match node {
220+ hir:: Node :: Expr ( _) => hir_id,
221+ hir:: Node :: Block ( b) => b. expr . map_or_else (
222+ // If there is no tail expression, there will be at least one statement in the
223+ // block because the block contains a break or continue statement.
224+ || b. stmts . last ( ) . unwrap ( ) . hir_id ,
225+ |expr| expr. hir_id ,
226+ ) ,
227+ hir:: Node :: Param ( ..)
228+ | hir:: Node :: Item ( ..)
229+ | hir:: Node :: ForeignItem ( ..)
230+ | hir:: Node :: TraitItem ( ..)
231+ | hir:: Node :: ImplItem ( ..)
232+ | hir:: Node :: Variant ( ..)
233+ | hir:: Node :: Field ( ..)
234+ | hir:: Node :: AnonConst ( ..)
235+ | hir:: Node :: Stmt ( ..)
236+ | hir:: Node :: PathSegment ( ..)
237+ | hir:: Node :: Ty ( ..)
238+ | hir:: Node :: TraitRef ( ..)
239+ | hir:: Node :: Binding ( ..)
240+ | hir:: Node :: Pat ( ..)
241+ | hir:: Node :: Arm ( ..)
242+ | hir:: Node :: Local ( ..)
243+ | hir:: Node :: Ctor ( ..)
244+ | hir:: Node :: Lifetime ( ..)
245+ | hir:: Node :: GenericParam ( ..)
246+ | hir:: Node :: Visibility ( ..)
247+ | hir:: Node :: Crate ( ..)
248+ | hir:: Node :: Infer ( ..) => bug ! ( "Unsupported branch target: {:?}" , node) ,
249+ }
250+ }
212251}
213252
214253impl < ' a , ' tcx > Visitor < ' tcx > for DropRangeVisitor < ' a , ' tcx > {
@@ -334,7 +373,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
334373 }
335374 ExprKind :: Break ( hir:: Destination { target_id : Ok ( target) , .. } , ..)
336375 | ExprKind :: Continue ( hir:: Destination { target_id : Ok ( target) , .. } , ..) => {
337- self . drop_ranges . add_control_edge_hir_id ( self . expr_index , target) ;
376+ self . drop_ranges
377+ . add_control_edge_hir_id ( self . expr_index , self . find_target_expression ( target) ) ;
338378 }
339379
340380 ExprKind :: Call ( f, args) => {
@@ -462,11 +502,13 @@ impl DropRangesBuilder {
462502 /// Should be called after visiting the HIR but before solving the control flow, otherwise some
463503 /// edges will be missed.
464504 fn process_deferred_edges ( & mut self ) {
505+ trace ! ( "processing deferred edges. post_order_map={:#?}" , self . post_order_map) ;
465506 let mut edges = vec ! [ ] ;
466507 swap ( & mut edges, & mut self . deferred_edges ) ;
467508 edges. into_iter ( ) . for_each ( |( from, to) | {
468- let to = * self . post_order_map . get ( & to) . expect ( "Expression ID not found" ) ;
469509 trace ! ( "Adding deferred edge from {:?} to {:?}" , from, to) ;
510+ let to = * self . post_order_map . get ( & to) . expect ( "Expression ID not found" ) ;
511+ trace ! ( "target edge PostOrderId={:?}" , to) ;
470512 self . add_control_edge ( from, to)
471513 } ) ;
472514 }
0 commit comments