@@ -283,7 +283,7 @@ impl<'tcx> Scopes<'tcx> {
283
283
284
284
/// Returns the topmost active scope, which is known to be alive until
285
285
/// the next scope expression.
286
- pub ( super ) fn topmost ( & self ) -> region:: Scope {
286
+ fn topmost ( & self ) -> region:: Scope {
287
287
self . scopes . last ( ) . expect ( "topmost_scope: no scopes present" ) . region_scope
288
288
}
289
289
@@ -297,7 +297,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
297
297
// ==========================
298
298
// Start a breakable scope, which tracks where `continue`, `break` and
299
299
// `return` should branch to.
300
- pub fn in_breakable_scope < F > (
300
+ crate fn in_breakable_scope < F > (
301
301
& mut self ,
302
302
loop_block : Option < BasicBlock > ,
303
303
break_destination : Place < ' tcx > ,
@@ -547,7 +547,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
547
547
///
548
548
/// This path terminates in GeneratorDrop. Returns the start of the path.
549
549
/// None indicates there’s no cleanup to do at this point.
550
- pub fn generator_drop_cleanup ( & mut self , yield_block : BasicBlock ) {
550
+ crate fn generator_drop_cleanup ( & mut self , yield_block : BasicBlock ) {
551
551
let drops = self . scopes . scopes . iter ( ) . flat_map ( |scope| & scope. drops ) ;
552
552
let mut next_drop = ROOT_NODE ;
553
553
for drop in drops {
@@ -832,7 +832,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
832
832
///
833
833
/// This path terminates in Resume. The path isn't created until after all
834
834
/// of the non-unwind paths in this item have been lowered.
835
- pub fn diverge_from ( & mut self , start : BasicBlock ) {
835
+ crate fn diverge_from ( & mut self , start : BasicBlock ) {
836
836
let next_drop = self . diverge_cleanup ( ) ;
837
837
self . scopes . unwind_drops . add_entry ( start, next_drop) ;
838
838
}
@@ -887,7 +887,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
887
887
///
888
888
/// This is only needed for `match` arm scopes, because they have one
889
889
/// entrance per pattern, but only one exit.
890
- pub ( crate ) fn clear_top_scope ( & mut self , region_scope : region:: Scope ) {
890
+ crate fn clear_top_scope ( & mut self , region_scope : region:: Scope ) {
891
891
let top_scope = self . scopes . scopes . last_mut ( ) . unwrap ( ) ;
892
892
893
893
assert_eq ! ( top_scope. region_scope, region_scope) ;
@@ -1018,38 +1018,38 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
1018
1018
1019
1019
crate fn build_drop_trees ( & mut self , should_abort : bool ) {
1020
1020
if self . is_generator {
1021
- Self :: build_generator_drop_tree (
1021
+ self . build_generator_drop_trees ( should_abort) ;
1022
+ } else {
1023
+ Self :: build_unwind_tree (
1022
1024
& mut self . cfg ,
1023
- & mut self . scopes . generator_drops ,
1025
+ & mut self . scopes . unwind_drops ,
1024
1026
self . fn_span ,
1025
1027
should_abort,
1026
1028
) ;
1027
1029
}
1028
- Self :: build_unwind_tree (
1029
- & mut self . cfg ,
1030
- & mut self . scopes . unwind_drops ,
1031
- self . fn_span ,
1032
- should_abort,
1033
- ) ;
1034
1030
}
1035
1031
1036
- fn build_generator_drop_tree (
1037
- cfg : & mut CFG < ' tcx > ,
1038
- drops : & mut DropTree ,
1039
- fn_span : Span ,
1040
- should_abort : bool ,
1041
- ) {
1032
+ fn build_generator_drop_trees ( & mut self , should_abort : bool ) {
1033
+ // Build the drop tree for dropping the generator while it's suspended.
1034
+ let drops = & mut self . scopes . generator_drops ;
1035
+ let cfg = & mut self . cfg ;
1036
+ let fn_span = self . fn_span ;
1042
1037
let mut blocks = IndexVec :: from_elem ( None , & drops. drops ) ;
1043
1038
build_drop_tree :: < GeneratorDrop > ( cfg, drops, & mut blocks) ;
1044
- // TODO: unwind?
1045
1039
if let Some ( root_block) = blocks[ ROOT_NODE ] {
1046
1040
cfg. terminate (
1047
1041
root_block,
1048
1042
SourceInfo { scope : OUTERMOST_SOURCE_SCOPE , span : fn_span } ,
1049
1043
TerminatorKind :: GeneratorDrop ,
1050
1044
) ;
1051
1045
}
1052
- // Reuse the generator drop tree as the unwind tree.
1046
+
1047
+ // Build the drop tree for unwinding in the normal control flow paths.
1048
+ let resume_block =
1049
+ Self :: build_unwind_tree ( cfg, & mut self . scopes . unwind_drops , fn_span, should_abort) ;
1050
+
1051
+ // Build the drop tree for unwinding when dropping a suspended
1052
+ // generator.
1053
1053
//
1054
1054
// This is a different tree to the standard unwind paths here to
1055
1055
// prevent drop elaboration from creating drop flags that would have
@@ -1060,15 +1060,26 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
1060
1060
drops. entry_points . push ( ( drop_data. 1 , blocks[ drop_idx] . unwrap ( ) ) ) ;
1061
1061
}
1062
1062
}
1063
- Self :: build_unwind_tree ( cfg, drops, fn_span, should_abort) ;
1063
+ let mut blocks = IndexVec :: from_elem ( None , & drops. drops ) ;
1064
+ blocks[ ROOT_NODE ] = resume_block;
1065
+ build_drop_tree :: < Unwind > ( cfg, drops, & mut blocks) ;
1066
+ if let ( None , Some ( new_resume_block) ) = ( resume_block, blocks[ ROOT_NODE ] ) {
1067
+ let terminator =
1068
+ if should_abort { TerminatorKind :: Abort } else { TerminatorKind :: Resume } ;
1069
+ cfg. terminate (
1070
+ new_resume_block,
1071
+ SourceInfo { scope : OUTERMOST_SOURCE_SCOPE , span : fn_span } ,
1072
+ terminator,
1073
+ ) ;
1074
+ }
1064
1075
}
1065
1076
1066
1077
fn build_unwind_tree (
1067
1078
cfg : & mut CFG < ' tcx > ,
1068
1079
drops : & mut DropTree ,
1069
1080
fn_span : Span ,
1070
1081
should_abort : bool ,
1071
- ) {
1082
+ ) -> Option < BasicBlock > {
1072
1083
let mut blocks = IndexVec :: from_elem ( None , & drops. drops ) ;
1073
1084
build_drop_tree :: < Unwind > ( cfg, drops, & mut blocks) ;
1074
1085
if let Some ( resume_block) = blocks[ ROOT_NODE ] {
@@ -1079,6 +1090,9 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
1079
1090
SourceInfo { scope : OUTERMOST_SOURCE_SCOPE , span : fn_span } ,
1080
1091
terminator,
1081
1092
) ;
1093
+ Some ( resume_block)
1094
+ } else {
1095
+ None
1082
1096
}
1083
1097
}
1084
1098
}
0 commit comments