@@ -383,7 +383,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
383
383
assert_eq ! ( scope. region_scope, region_scope. 0 ) ;
384
384
385
385
self . cfg . push_end_region ( self . hir . tcx ( ) , block, region_scope. 1 , scope. region_scope ) ;
386
+ let resume_block = self . resume_block ( ) ;
386
387
unpack ! ( block = build_scope_drops( & mut self . cfg,
388
+ resume_block,
387
389
& scope,
388
390
& self . scopes,
389
391
block,
@@ -422,6 +424,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
422
424
}
423
425
424
426
{
427
+ let resume_block = self . resume_block ( ) ;
425
428
let mut rest = & mut self . scopes [ ( len - scope_count) ..] ;
426
429
while let Some ( ( scope, rest_) ) = { rest} . split_last_mut ( ) {
427
430
rest = rest_;
@@ -441,6 +444,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
441
444
self . cfg . push_end_region ( self . hir . tcx ( ) , block, region_scope. 1 , scope. region_scope ) ;
442
445
443
446
unpack ! ( block = build_scope_drops( & mut self . cfg,
447
+ resume_block,
444
448
scope,
445
449
rest,
446
450
block,
@@ -468,6 +472,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
468
472
let src_info = self . scopes [ 0 ] . source_info ( self . fn_span ) ;
469
473
let mut block = self . cfg . start_new_block ( ) ;
470
474
let result = block;
475
+ let resume_block = self . resume_block ( ) ;
471
476
let mut rest = & mut self . scopes [ ..] ;
472
477
473
478
while let Some ( ( scope, rest_) ) = { rest} . split_last_mut ( ) {
@@ -491,6 +496,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
491
496
self . cfg . push_end_region ( self . hir . tcx ( ) , block, src_info, scope. region_scope ) ;
492
497
493
498
unpack ! ( block = build_scope_drops( & mut self . cfg,
499
+ resume_block,
494
500
scope,
495
501
rest,
496
502
block,
@@ -701,18 +707,31 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
701
707
/// This path terminates in Resume. Returns the start of the path.
702
708
/// See module comment for more details. None indicates there’s no
703
709
/// cleanup to do at this point.
704
- pub fn diverge_cleanup ( & mut self ) -> Option < BasicBlock > {
710
+ pub fn diverge_cleanup ( & mut self ) -> BasicBlock {
705
711
self . diverge_cleanup_gen ( false )
706
712
}
707
713
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
711
727
}
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 ( ) ;
713
733
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 ;
716
735
717
736
// Build up the drops in **reverse** order. The end result will
718
737
// look like:
@@ -725,23 +744,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
725
744
// store caches. If everything is cached, we'll just walk right
726
745
// to left reading the cached results but never created anything.
727
746
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
+ }
743
752
}
744
- Some ( target)
753
+
754
+ target
745
755
}
746
756
747
757
/// Utility function for *non*-scope code to build their own drops
@@ -760,7 +770,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
760
770
TerminatorKind :: Drop {
761
771
location,
762
772
target : next_target,
763
- unwind : diverge_target,
773
+ unwind : Some ( diverge_target) ,
764
774
} ) ;
765
775
next_target. unit ( )
766
776
}
@@ -779,7 +789,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
779
789
location,
780
790
value,
781
791
target : next_target,
782
- unwind : diverge_target,
792
+ unwind : Some ( diverge_target) ,
783
793
} ) ;
784
794
next_target. unit ( )
785
795
}
@@ -804,7 +814,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
804
814
expected,
805
815
msg,
806
816
target : success_block,
807
- cleanup,
817
+ cleanup : Some ( cleanup ) ,
808
818
} ) ;
809
819
810
820
success_block
@@ -813,6 +823,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
813
823
814
824
/// Builds drops for pop_scope and exit_scope.
815
825
fn build_scope_drops < ' tcx > ( cfg : & mut CFG < ' tcx > ,
826
+ resume_block : BasicBlock ,
816
827
scope : & Scope < ' tcx > ,
817
828
earlier_scopes : & [ Scope < ' tcx > ] ,
818
829
mut block : BasicBlock ,
@@ -868,7 +879,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
868
879
cfg. terminate ( block, source_info, TerminatorKind :: Drop {
869
880
location : drop_data. location . clone ( ) ,
870
881
target : next,
871
- unwind : on_diverge
882
+ unwind : Some ( on_diverge. unwrap_or ( resume_block ) )
872
883
} ) ;
873
884
block = next;
874
885
}
0 commit comments