@@ -816,9 +816,28 @@ pub enum TerminatorKind<'tcx> {
816816 /// Indicates the end of the dropping of a generator
817817 GeneratorDrop ,
818818
819+ /// A block where control flow only ever takes one real path, but borrowck
820+ /// needs to be more conservative.
819821 FalseEdges {
822+ /// The target normal control flow will take
820823 real_target : BasicBlock ,
821- imaginary_targets : Vec < BasicBlock >
824+ /// The list of blocks control flow could conceptually take, but won't
825+ /// in practice
826+ imaginary_targets : Vec < BasicBlock > ,
827+ } ,
828+ /// A terminator for blocks that only take one path in reality, but where we
829+ /// reserve the right to unwind in borrowck, even if it won't happen in practice.
830+ /// This can arise in infinite loops with no function calls for example.
831+ FalseUnwind {
832+ /// The target normal control flow will take
833+ real_target : BasicBlock ,
834+ /// The imaginary cleanup block link. This particular path will never be taken
835+ /// in practice, but in order to avoid fragility we want to always
836+ /// consider it in borrowck. We don't want to accept programs which
837+ /// pass borrowck only when panic=abort or some assertions are disabled
838+ /// due to release vs. debug mode builds. This needs to be an Option because
839+ /// of the remove_noop_landing_pads and no_landing_pads passes
840+ unwind : Option < BasicBlock > ,
822841 } ,
823842}
824843
@@ -878,6 +897,8 @@ impl<'tcx> TerminatorKind<'tcx> {
878897 s. extend_from_slice ( imaginary_targets) ;
879898 s. into_cow ( )
880899 }
900+ FalseUnwind { real_target : t, unwind : Some ( u) } => vec ! [ t, u] . into_cow ( ) ,
901+ FalseUnwind { real_target : ref t, unwind : None } => slice:: from_ref ( t) . into_cow ( ) ,
881902 }
882903 }
883904
@@ -910,6 +931,8 @@ impl<'tcx> TerminatorKind<'tcx> {
910931 s. extend ( imaginary_targets. iter_mut ( ) ) ;
911932 s
912933 }
934+ FalseUnwind { real_target : ref mut t, unwind : Some ( ref mut u) } => vec ! [ t, u] ,
935+ FalseUnwind { ref mut real_target, unwind : None } => vec ! [ real_target] ,
913936 }
914937 }
915938
@@ -929,7 +952,8 @@ impl<'tcx> TerminatorKind<'tcx> {
929952 TerminatorKind :: Call { cleanup : ref mut unwind, .. } |
930953 TerminatorKind :: Assert { cleanup : ref mut unwind, .. } |
931954 TerminatorKind :: DropAndReplace { ref mut unwind, .. } |
932- TerminatorKind :: Drop { ref mut unwind, .. } => {
955+ TerminatorKind :: Drop { ref mut unwind, .. } |
956+ TerminatorKind :: FalseUnwind { ref mut unwind, .. } => {
933957 Some ( unwind)
934958 }
935959 }
@@ -1058,7 +1082,8 @@ impl<'tcx> TerminatorKind<'tcx> {
10581082
10591083 write ! ( fmt, ")" )
10601084 } ,
1061- FalseEdges { .. } => write ! ( fmt, "falseEdges" )
1085+ FalseEdges { .. } => write ! ( fmt, "falseEdges" ) ,
1086+ FalseUnwind { .. } => write ! ( fmt, "falseUnwind" ) ,
10621087 }
10631088 }
10641089
@@ -1100,6 +1125,8 @@ impl<'tcx> TerminatorKind<'tcx> {
11001125 l. resize ( imaginary_targets. len ( ) + 1 , "imaginary" . into ( ) ) ;
11011126 l
11021127 }
1128+ FalseUnwind { unwind : Some ( _) , .. } => vec ! [ "real" . into( ) , "cleanup" . into( ) ] ,
1129+ FalseUnwind { unwind : None , .. } => vec ! [ "real" . into( ) ] ,
11031130 }
11041131 }
11051132}
@@ -2202,7 +2229,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
22022229 Return => Return ,
22032230 Unreachable => Unreachable ,
22042231 FalseEdges { real_target, ref imaginary_targets } =>
2205- FalseEdges { real_target, imaginary_targets : imaginary_targets. clone ( ) }
2232+ FalseEdges { real_target, imaginary_targets : imaginary_targets. clone ( ) } ,
2233+ FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind } ,
22062234 } ;
22072235 Terminator {
22082236 source_info : self . source_info ,
@@ -2244,7 +2272,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
22442272 Return |
22452273 GeneratorDrop |
22462274 Unreachable |
2247- FalseEdges { .. } => false
2275+ FalseEdges { .. } |
2276+ FalseUnwind { .. } => false
22482277 }
22492278 }
22502279}
0 commit comments