@@ -36,7 +36,7 @@ use hir::{self, InlineAsm};
36
36
use std:: borrow:: { Cow } ;
37
37
use rustc_data_structures:: sync:: ReadGuard ;
38
38
use std:: fmt:: { self , Debug , Formatter , Write } ;
39
- use std:: { iter, mem, u32} ;
39
+ use std:: { iter, mem, option , u32} ;
40
40
use std:: ops:: { Index , IndexMut } ;
41
41
use std:: vec:: IntoIter ;
42
42
use syntax:: ast:: { self , Name } ;
@@ -862,12 +862,17 @@ pub enum TerminatorKind<'tcx> {
862
862
} ,
863
863
}
864
864
865
+ pub type Successors < ' a > =
866
+ iter:: Chain < option:: IntoIter < & ' a BasicBlock > , slice:: Iter < ' a , BasicBlock > > ;
867
+ pub type SuccessorsMut < ' a > =
868
+ iter:: Chain < option:: IntoIter < & ' a mut BasicBlock > , slice:: IterMut < ' a , BasicBlock > > ;
869
+
865
870
impl < ' tcx > Terminator < ' tcx > {
866
- pub fn successors ( & self ) -> Cow < [ BasicBlock ] > {
871
+ pub fn successors ( & self ) -> Successors {
867
872
self . kind . successors ( )
868
873
}
869
874
870
- pub fn successors_mut ( & mut self ) -> Vec < & mut BasicBlock > {
875
+ pub fn successors_mut ( & mut self ) -> SuccessorsMut {
871
876
self . kind . successors_mut ( )
872
877
}
873
878
@@ -888,72 +893,71 @@ impl<'tcx> TerminatorKind<'tcx> {
888
893
}
889
894
}
890
895
891
- pub fn successors ( & self ) -> Cow < [ BasicBlock ] > {
896
+ pub fn successors ( & self ) -> Successors {
892
897
use self :: TerminatorKind :: * ;
893
898
match * self {
894
- Goto { target : ref b } => slice:: from_ref ( b) . into_cow ( ) ,
895
- SwitchInt { targets : ref b, .. } => b[ ..] . into_cow ( ) ,
896
- Resume | Abort | GeneratorDrop => ( & [ ] ) . into_cow ( ) ,
897
- Return => ( & [ ] ) . into_cow ( ) ,
898
- Unreachable => ( & [ ] ) . into_cow ( ) ,
899
- Call { destination : Some ( ( _, t) ) , cleanup : Some ( c) , .. } => vec ! [ t, c] . into_cow ( ) ,
900
- Call { destination : Some ( ( _, ref t) ) , cleanup : None , .. } =>
901
- slice:: from_ref ( t) . into_cow ( ) ,
902
- Call { destination : None , cleanup : Some ( ref c) , .. } => slice:: from_ref ( c) . into_cow ( ) ,
903
- Call { destination : None , cleanup : None , .. } => ( & [ ] ) . into_cow ( ) ,
904
- Yield { resume : t, drop : Some ( c) , .. } => vec ! [ t, c] . into_cow ( ) ,
905
- Yield { resume : ref t, drop : None , .. } => slice:: from_ref ( t) . into_cow ( ) ,
906
- DropAndReplace { target, unwind : Some ( unwind) , .. } |
907
- Drop { target, unwind : Some ( unwind) , .. } => {
908
- vec ! [ target, unwind] . into_cow ( )
899
+ Resume | Abort | GeneratorDrop | Return | Unreachable |
900
+ Call { destination : None , cleanup : None , .. } => {
901
+ None . into_iter ( ) . chain ( & [ ] )
902
+ }
903
+ Goto { target : ref t } |
904
+ Call { destination : None , cleanup : Some ( ref t) , .. } |
905
+ Call { destination : Some ( ( _, ref t) ) , cleanup : None , .. } |
906
+ Yield { resume : ref t, drop : None , .. } |
907
+ DropAndReplace { target : ref t, unwind : None , .. } |
908
+ Drop { target : ref t, unwind : None , .. } |
909
+ Assert { target : ref t, cleanup : None , .. } |
910
+ FalseUnwind { real_target : ref t, unwind : None } => {
911
+ Some ( t) . into_iter ( ) . chain ( & [ ] )
909
912
}
910
- DropAndReplace { ref target, unwind : None , .. } |
911
- Drop { ref target, unwind : None , .. } => {
912
- slice:: from_ref ( target) . into_cow ( )
913
+ Call { destination : Some ( ( _, ref t) ) , cleanup : Some ( ref u) , .. } |
914
+ Yield { resume : ref t, drop : Some ( ref u) , .. } |
915
+ DropAndReplace { target : ref t, unwind : Some ( ref u) , .. } |
916
+ Drop { target : ref t, unwind : Some ( ref u) , .. } |
917
+ Assert { target : ref t, cleanup : Some ( ref u) , .. } |
918
+ FalseUnwind { real_target : ref t, unwind : Some ( ref u) } => {
919
+ Some ( t) . into_iter ( ) . chain ( slice:: from_ref ( u) )
920
+ }
921
+ SwitchInt { ref targets, .. } => {
922
+ None . into_iter ( ) . chain ( & targets[ ..] )
913
923
}
914
- Assert { target, cleanup : Some ( unwind) , .. } => vec ! [ target, unwind] . into_cow ( ) ,
915
- Assert { ref target, .. } => slice:: from_ref ( target) . into_cow ( ) ,
916
924
FalseEdges { ref real_target, ref imaginary_targets } => {
917
- let mut s = vec ! [ * real_target] ;
918
- s. extend_from_slice ( imaginary_targets) ;
919
- s. into_cow ( )
925
+ Some ( real_target) . into_iter ( ) . chain ( & imaginary_targets[ ..] )
920
926
}
921
- FalseUnwind { real_target : t, unwind : Some ( u) } => vec ! [ t, u] . into_cow ( ) ,
922
- FalseUnwind { real_target : ref t, unwind : None } => slice:: from_ref ( t) . into_cow ( ) ,
923
927
}
924
928
}
925
929
926
- // FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and
927
- // `Vec<&mut BasicBlock>` would look like in the first place.
928
- pub fn successors_mut ( & mut self ) -> Vec < & mut BasicBlock > {
930
+ pub fn successors_mut ( & mut self ) -> SuccessorsMut {
929
931
use self :: TerminatorKind :: * ;
930
932
match * self {
931
- Goto { target : ref mut b } => vec ! [ b] ,
932
- SwitchInt { targets : ref mut b, .. } => b. iter_mut ( ) . collect ( ) ,
933
- Resume | Abort | GeneratorDrop => Vec :: new ( ) ,
934
- Return => Vec :: new ( ) ,
935
- Unreachable => Vec :: new ( ) ,
936
- Call { destination : Some ( ( _, ref mut t) ) , cleanup : Some ( ref mut c) , .. } => vec ! [ t, c] ,
937
- Call { destination : Some ( ( _, ref mut t) ) , cleanup : None , .. } => vec ! [ t] ,
938
- Call { destination : None , cleanup : Some ( ref mut c) , .. } => vec ! [ c] ,
939
- Call { destination : None , cleanup : None , .. } => vec ! [ ] ,
940
- Yield { resume : ref mut t, drop : Some ( ref mut c) , .. } => vec ! [ t, c] ,
941
- Yield { resume : ref mut t, drop : None , .. } => vec ! [ t] ,
942
- DropAndReplace { ref mut target, unwind : Some ( ref mut unwind) , .. } |
943
- Drop { ref mut target, unwind : Some ( ref mut unwind) , .. } => vec ! [ target, unwind] ,
944
- DropAndReplace { ref mut target, unwind : None , .. } |
945
- Drop { ref mut target, unwind : None , .. } => {
946
- vec ! [ target]
933
+ Resume | Abort | GeneratorDrop | Return | Unreachable |
934
+ Call { destination : None , cleanup : None , .. } => {
935
+ None . into_iter ( ) . chain ( & mut [ ] )
936
+ }
937
+ Goto { target : ref mut t } |
938
+ Call { destination : None , cleanup : Some ( ref mut t) , .. } |
939
+ Call { destination : Some ( ( _, ref mut t) ) , cleanup : None , .. } |
940
+ Yield { resume : ref mut t, drop : None , .. } |
941
+ DropAndReplace { target : ref mut t, unwind : None , .. } |
942
+ Drop { target : ref mut t, unwind : None , .. } |
943
+ Assert { target : ref mut t, cleanup : None , .. } |
944
+ FalseUnwind { real_target : ref mut t, unwind : None } => {
945
+ Some ( t) . into_iter ( ) . chain ( & mut [ ] )
946
+ }
947
+ Call { destination : Some ( ( _, ref mut t) ) , cleanup : Some ( ref mut u) , .. } |
948
+ Yield { resume : ref mut t, drop : Some ( ref mut u) , .. } |
949
+ DropAndReplace { target : ref mut t, unwind : Some ( ref mut u) , .. } |
950
+ Drop { target : ref mut t, unwind : Some ( ref mut u) , .. } |
951
+ Assert { target : ref mut t, cleanup : Some ( ref mut u) , .. } |
952
+ FalseUnwind { real_target : ref mut t, unwind : Some ( ref mut u) } => {
953
+ Some ( t) . into_iter ( ) . chain ( slice:: from_ref_mut ( u) )
954
+ }
955
+ SwitchInt { ref mut targets, .. } => {
956
+ None . into_iter ( ) . chain ( & mut targets[ ..] )
947
957
}
948
- Assert { ref mut target, cleanup : Some ( ref mut unwind) , .. } => vec ! [ target, unwind] ,
949
- Assert { ref mut target, .. } => vec ! [ target] ,
950
958
FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
951
- let mut s = vec ! [ real_target] ;
952
- s. extend ( imaginary_targets. iter_mut ( ) ) ;
953
- s
959
+ Some ( real_target) . into_iter ( ) . chain ( & mut imaginary_targets[ ..] )
954
960
}
955
- FalseUnwind { real_target : ref mut t, unwind : Some ( ref mut u) } => vec ! [ t, u] ,
956
- FalseUnwind { ref mut real_target, unwind : None } => vec ! [ real_target] ,
957
961
}
958
962
}
959
963
@@ -1073,18 +1077,18 @@ impl<'tcx> BasicBlockData<'tcx> {
1073
1077
impl < ' tcx > Debug for TerminatorKind < ' tcx > {
1074
1078
fn fmt ( & self , fmt : & mut Formatter ) -> fmt:: Result {
1075
1079
self . fmt_head ( fmt) ?;
1076
- let successors = self . successors ( ) ;
1080
+ let successor_count = self . successors ( ) . count ( ) ;
1077
1081
let labels = self . fmt_successor_labels ( ) ;
1078
- assert_eq ! ( successors . len ( ) , labels. len( ) ) ;
1082
+ assert_eq ! ( successor_count , labels. len( ) ) ;
1079
1083
1080
- match successors . len ( ) {
1084
+ match successor_count {
1081
1085
0 => Ok ( ( ) ) ,
1082
1086
1083
- 1 => write ! ( fmt, " -> {:?}" , successors[ 0 ] ) ,
1087
+ 1 => write ! ( fmt, " -> {:?}" , self . successors( ) . nth ( 0 ) . unwrap ( ) ) ,
1084
1088
1085
1089
_ => {
1086
1090
write ! ( fmt, " -> [" ) ?;
1087
- for ( i, target) in successors . iter ( ) . enumerate ( ) {
1091
+ for ( i, target) in self . successors ( ) . enumerate ( ) {
1088
1092
if i > 0 {
1089
1093
write ! ( fmt, ", " ) ?;
1090
1094
}
@@ -1943,7 +1947,7 @@ impl<'tcx> ControlFlowGraph for Mir<'tcx> {
1943
1947
fn successors < ' graph > ( & ' graph self , node : Self :: Node )
1944
1948
-> <Self as GraphSuccessors < ' graph > >:: Iter
1945
1949
{
1946
- self . basic_blocks [ node] . terminator ( ) . successors ( ) . into_owned ( ) . into_iter ( )
1950
+ self . basic_blocks [ node] . terminator ( ) . successors ( ) . cloned ( )
1947
1951
}
1948
1952
}
1949
1953
@@ -1954,7 +1958,7 @@ impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> {
1954
1958
1955
1959
impl < ' a , ' b > GraphSuccessors < ' b > for Mir < ' a > {
1956
1960
type Item = BasicBlock ;
1957
- type Iter = IntoIter < BasicBlock > ;
1961
+ type Iter = iter :: Cloned < Successors < ' b > > ;
1958
1962
}
1959
1963
1960
1964
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Ord , PartialOrd ) ]
0 commit comments