@@ -383,7 +383,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
383383 assert_eq ! ( scope. region_scope, region_scope. 0 ) ;
384384
385385 self . cfg . push_end_region ( self . hir . tcx ( ) , block, region_scope. 1 , scope. region_scope ) ;
386+ let resume_block = self . resume_block ( ) ;
386387 unpack ! ( block = build_scope_drops( & mut self . cfg,
388+ resume_block,
387389 & scope,
388390 & self . scopes,
389391 block,
@@ -422,6 +424,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
422424 }
423425
424426 {
427+ let resume_block = self . resume_block ( ) ;
425428 let mut rest = & mut self . scopes [ ( len - scope_count) ..] ;
426429 while let Some ( ( scope, rest_) ) = { rest} . split_last_mut ( ) {
427430 rest = rest_;
@@ -441,6 +444,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
441444 self . cfg . push_end_region ( self . hir . tcx ( ) , block, region_scope. 1 , scope. region_scope ) ;
442445
443446 unpack ! ( block = build_scope_drops( & mut self . cfg,
447+ resume_block,
444448 scope,
445449 rest,
446450 block,
@@ -468,6 +472,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
468472 let src_info = self . scopes [ 0 ] . source_info ( self . fn_span ) ;
469473 let mut block = self . cfg . start_new_block ( ) ;
470474 let result = block;
475+ let resume_block = self . resume_block ( ) ;
471476 let mut rest = & mut self . scopes [ ..] ;
472477
473478 while let Some ( ( scope, rest_) ) = { rest} . split_last_mut ( ) {
@@ -491,6 +496,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
491496 self . cfg . push_end_region ( self . hir . tcx ( ) , block, src_info, scope. region_scope ) ;
492497
493498 unpack ! ( block = build_scope_drops( & mut self . cfg,
499+ resume_block,
494500 scope,
495501 rest,
496502 block,
@@ -701,18 +707,31 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
701707 /// This path terminates in Resume. Returns the start of the path.
702708 /// See module comment for more details. None indicates there’s no
703709 /// cleanup to do at this point.
704- pub fn diverge_cleanup ( & mut self ) -> Option < BasicBlock > {
710+ pub fn diverge_cleanup ( & mut self ) -> BasicBlock {
705711 self . diverge_cleanup_gen ( false )
706712 }
707713
708- fn diverge_cleanup_gen ( & mut self , generator_drop : bool ) -> Option < BasicBlock > {
709- if !self . scopes . iter ( ) . any ( |scope| scope. needs_cleanup ) {
710- return None ;
714+ fn resume_block ( & mut self ) -> BasicBlock {
715+ if let Some ( target) = self . cached_resume_block {
716+ target
717+ } else {
718+ let resumeblk = self . cfg . start_new_cleanup_block ( ) ;
719+ self . cfg . terminate ( resumeblk,
720+ SourceInfo {
721+ scope : ARGUMENT_VISIBILITY_SCOPE ,
722+ span : self . fn_span
723+ } ,
724+ TerminatorKind :: Resume ) ;
725+ self . cached_resume_block = Some ( resumeblk) ;
726+ resumeblk
711727 }
712- assert ! ( !self . scopes. is_empty( ) ) ; // or `any` above would be false
728+ }
729+
730+ fn diverge_cleanup_gen ( & mut self , generator_drop : bool ) -> BasicBlock {
731+ // To start, create the resume terminator.
732+ let mut target = self . resume_block ( ) ;
713733
714- let Builder { ref mut cfg, ref mut scopes,
715- ref mut cached_resume_block, .. } = * self ;
734+ let Builder { ref mut cfg, ref mut scopes, .. } = * self ;
716735
717736 // Build up the drops in **reverse** order. The end result will
718737 // look like:
@@ -725,23 +744,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
725744 // store caches. If everything is cached, we'll just walk right
726745 // to left reading the cached results but never created anything.
727746
728- // To start, create the resume terminator.
729- let mut target = if let Some ( target) = * cached_resume_block {
730- target
731- } else {
732- let resumeblk = cfg. start_new_cleanup_block ( ) ;
733- cfg. terminate ( resumeblk,
734- scopes[ 0 ] . source_info ( self . fn_span ) ,
735- TerminatorKind :: Resume ) ;
736- * cached_resume_block = Some ( resumeblk) ;
737- resumeblk
738- } ;
739-
740- for scope in scopes. iter_mut ( ) {
741- target = build_diverge_scope ( self . hir . tcx ( ) , cfg, scope. region_scope_span ,
742- scope, target, generator_drop) ;
747+ if scopes. iter ( ) . any ( |scope| scope. needs_cleanup ) {
748+ for scope in scopes. iter_mut ( ) {
749+ target = build_diverge_scope ( self . hir . tcx ( ) , cfg, scope. region_scope_span ,
750+ scope, target, generator_drop) ;
751+ }
743752 }
744- Some ( target)
753+
754+ target
745755 }
746756
747757 /// Utility function for *non*-scope code to build their own drops
@@ -760,7 +770,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
760770 TerminatorKind :: Drop {
761771 location,
762772 target : next_target,
763- unwind : diverge_target,
773+ unwind : Some ( diverge_target) ,
764774 } ) ;
765775 next_target. unit ( )
766776 }
@@ -779,7 +789,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
779789 location,
780790 value,
781791 target : next_target,
782- unwind : diverge_target,
792+ unwind : Some ( diverge_target) ,
783793 } ) ;
784794 next_target. unit ( )
785795 }
@@ -804,7 +814,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
804814 expected,
805815 msg,
806816 target : success_block,
807- cleanup,
817+ cleanup : Some ( cleanup ) ,
808818 } ) ;
809819
810820 success_block
@@ -813,6 +823,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
813823
814824/// Builds drops for pop_scope and exit_scope.
815825fn build_scope_drops < ' tcx > ( cfg : & mut CFG < ' tcx > ,
826+ resume_block : BasicBlock ,
816827 scope : & Scope < ' tcx > ,
817828 earlier_scopes : & [ Scope < ' tcx > ] ,
818829 mut block : BasicBlock ,
@@ -868,7 +879,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
868879 cfg. terminate ( block, source_info, TerminatorKind :: Drop {
869880 location : drop_data. location . clone ( ) ,
870881 target : next,
871- unwind : on_diverge
882+ unwind : Some ( on_diverge. unwrap_or ( resume_block ) )
872883 } ) ;
873884 block = next;
874885 }
0 commit comments