@@ -858,98 +858,98 @@ fn find_candidates<'a, 'tcx>(
858
858
tcx : TyCtxt < ' tcx > ,
859
859
body : & ' a Body < ' tcx > ,
860
860
) -> Vec < CandidateAssignment < ' tcx > > {
861
- struct FindAssignments < ' a , ' tcx > {
862
- tcx : TyCtxt < ' tcx > ,
863
- body : & ' a Body < ' tcx > ,
864
- candidates : Vec < CandidateAssignment < ' tcx > > ,
865
- ever_borrowed_locals : BitSet < Local > ,
866
- locals_used_as_array_index : BitSet < Local > ,
867
- }
861
+ let mut visitor = FindAssignments {
862
+ tcx,
863
+ body,
864
+ candidates : Vec :: new ( ) ,
865
+ ever_borrowed_locals : ever_borrowed_locals ( body) ,
866
+ locals_used_as_array_index : locals_used_as_array_index ( body) ,
867
+ } ;
868
+ visitor. visit_body ( body) ;
869
+ visitor. candidates
870
+ }
868
871
869
- impl < ' a , ' tcx > Visitor < ' tcx > for FindAssignments < ' a , ' tcx > {
870
- fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
871
- if let StatementKind :: Assign ( box (
872
- dest,
873
- Rvalue :: Use ( Operand :: Copy ( src) | Operand :: Move ( src) ) ,
874
- ) ) = & statement. kind
875
- {
876
- // `dest` must not have pointer indirection.
877
- if dest. is_indirect ( ) {
878
- return ;
879
- }
872
+ struct FindAssignments < ' a , ' tcx > {
873
+ tcx : TyCtxt < ' tcx > ,
874
+ body : & ' a Body < ' tcx > ,
875
+ candidates : Vec < CandidateAssignment < ' tcx > > ,
876
+ ever_borrowed_locals : BitSet < Local > ,
877
+ locals_used_as_array_index : BitSet < Local > ,
878
+ }
880
879
881
- // `src` must be a plain local.
882
- if !src. projection . is_empty ( ) {
883
- return ;
884
- }
880
+ impl < ' a , ' tcx > Visitor < ' tcx > for FindAssignments < ' a , ' tcx > {
881
+ fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
882
+ if let StatementKind :: Assign ( box (
883
+ dest,
884
+ Rvalue :: Use ( Operand :: Copy ( src) | Operand :: Move ( src) ) ,
885
+ ) ) = & statement. kind
886
+ {
887
+ // `dest` must not have pointer indirection.
888
+ if dest. is_indirect ( ) {
889
+ return ;
890
+ }
885
891
886
- // Since we want to replace `src` with `dest`, `src` must not be required .
887
- if is_local_required ( src. local , self . body ) {
888
- return ;
889
- }
892
+ // `src` must be a plain local .
893
+ if ! src. projection . is_empty ( ) {
894
+ return ;
895
+ }
890
896
891
- // Can't optimize if both locals ever have their address taken (can introduce
892
- // aliasing).
893
- // FIXME: This can be smarter and take `StorageDead` into account (which
894
- // invalidates borrows).
895
- if self . ever_borrowed_locals . contains ( dest. local )
896
- && self . ever_borrowed_locals . contains ( src. local )
897
- {
898
- return ;
899
- }
897
+ // Since we want to replace `src` with `dest`, `src` must not be required.
898
+ if is_local_required ( src. local , self . body ) {
899
+ return ;
900
+ }
900
901
901
- assert_ne ! ( dest. local, src. local, "self-assignments are UB" ) ;
902
+ // Can't optimize if both locals ever have their address taken (can introduce
903
+ // aliasing).
904
+ // FIXME: This can be smarter and take `StorageDead` into account (which
905
+ // invalidates borrows).
906
+ if self . ever_borrowed_locals . contains ( dest. local )
907
+ && self . ever_borrowed_locals . contains ( src. local )
908
+ {
909
+ return ;
910
+ }
902
911
903
- // We can't replace locals occurring in `PlaceElem::Index` for now.
904
- if self . locals_used_as_array_index . contains ( src. local ) {
905
- return ;
906
- }
912
+ assert_ne ! ( dest. local, src. local, "self-assignments are UB" ) ;
907
913
908
- // Handle the "subtle case" described above by rejecting any `dest` that is or
909
- // projects through a union.
910
- let is_union = |ty : Ty < ' _ > | {
911
- if let ty:: Adt ( def, _) = ty. kind ( ) {
912
- if def. is_union ( ) {
913
- return true ;
914
- }
914
+ // We can't replace locals occurring in `PlaceElem::Index` for now.
915
+ if self . locals_used_as_array_index . contains ( src. local ) {
916
+ return ;
917
+ }
918
+
919
+ // Handle the "subtle case" described above by rejecting any `dest` that is or
920
+ // projects through a union.
921
+ let is_union = |ty : Ty < ' _ > | {
922
+ if let ty:: Adt ( def, _) = ty. kind ( ) {
923
+ if def. is_union ( ) {
924
+ return true ;
915
925
}
926
+ }
916
927
917
- false
918
- } ;
919
- let mut place_ty = PlaceTy :: from_ty ( self . body . local_decls [ dest. local ] . ty ) ;
920
- if is_union ( place_ty. ty ) {
928
+ false
929
+ } ;
930
+ let mut place_ty = PlaceTy :: from_ty ( self . body . local_decls [ dest. local ] . ty ) ;
931
+ if is_union ( place_ty. ty ) {
932
+ return ;
933
+ }
934
+ for elem in dest. projection {
935
+ if let PlaceElem :: Index ( _) = elem {
936
+ // `dest` contains an indexing projection.
921
937
return ;
922
938
}
923
- for elem in dest. projection {
924
- if let PlaceElem :: Index ( _) = elem {
925
- // `dest` contains an indexing projection.
926
- return ;
927
- }
928
939
929
- place_ty = place_ty. projection_ty ( self . tcx , elem) ;
930
- if is_union ( place_ty. ty ) {
931
- return ;
932
- }
940
+ place_ty = place_ty. projection_ty ( self . tcx , elem) ;
941
+ if is_union ( place_ty. ty ) {
942
+ return ;
933
943
}
934
-
935
- self . candidates . push ( CandidateAssignment {
936
- dest : * dest,
937
- src : src. local ,
938
- loc : location,
939
- } ) ;
940
944
}
945
+
946
+ self . candidates . push ( CandidateAssignment {
947
+ dest : * dest,
948
+ src : src. local ,
949
+ loc : location,
950
+ } ) ;
941
951
}
942
952
}
943
-
944
- let mut visitor = FindAssignments {
945
- tcx,
946
- body,
947
- candidates : Vec :: new ( ) ,
948
- ever_borrowed_locals : ever_borrowed_locals ( body) ,
949
- locals_used_as_array_index : locals_used_as_array_index ( body) ,
950
- } ;
951
- visitor. visit_body ( body) ;
952
- visitor. candidates
953
953
}
954
954
955
955
/// Some locals are part of the function's interface and can not be removed.
@@ -965,92 +965,92 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
965
965
966
966
/// Walks MIR to find all locals that have their address taken anywhere.
967
967
fn ever_borrowed_locals ( body : & Body < ' _ > ) -> BitSet < Local > {
968
- struct BorrowCollector {
969
- locals : BitSet < Local > ,
970
- }
968
+ let mut visitor = BorrowCollector { locals : BitSet :: new_empty ( body. local_decls . len ( ) ) } ;
969
+ visitor. visit_body ( body) ;
970
+ visitor. locals
971
+ }
971
972
972
- impl < ' tcx > Visitor < ' tcx > for BorrowCollector {
973
- fn visit_rvalue ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) {
974
- self . super_rvalue ( rvalue , location ) ;
973
+ struct BorrowCollector {
974
+ locals : BitSet < Local > ,
975
+ }
975
976
976
- match rvalue {
977
- Rvalue :: AddressOf ( _, borrowed_place) | Rvalue :: Ref ( _, _, borrowed_place) => {
978
- if !borrowed_place. is_indirect ( ) {
979
- self . locals . insert ( borrowed_place. local ) ;
980
- }
981
- }
977
+ impl < ' tcx > Visitor < ' tcx > for BorrowCollector {
978
+ fn visit_rvalue ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) {
979
+ self . super_rvalue ( rvalue, location) ;
982
980
983
- Rvalue :: Cast ( ..)
984
- | Rvalue :: Use ( ..)
985
- | Rvalue :: Repeat ( ..)
986
- | Rvalue :: Len ( ..)
987
- | Rvalue :: BinaryOp ( ..)
988
- | Rvalue :: CheckedBinaryOp ( ..)
989
- | Rvalue :: NullaryOp ( ..)
990
- | Rvalue :: UnaryOp ( ..)
991
- | Rvalue :: Discriminant ( ..)
992
- | Rvalue :: Aggregate ( ..)
993
- | Rvalue :: ThreadLocalRef ( ..) => { }
981
+ match rvalue {
982
+ Rvalue :: AddressOf ( _, borrowed_place) | Rvalue :: Ref ( _, _, borrowed_place) => {
983
+ if !borrowed_place. is_indirect ( ) {
984
+ self . locals . insert ( borrowed_place. local ) ;
985
+ }
994
986
}
995
- }
996
987
997
- fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
998
- self . super_terminator ( terminator, location) ;
988
+ Rvalue :: Cast ( ..)
989
+ | Rvalue :: Use ( ..)
990
+ | Rvalue :: Repeat ( ..)
991
+ | Rvalue :: Len ( ..)
992
+ | Rvalue :: BinaryOp ( ..)
993
+ | Rvalue :: CheckedBinaryOp ( ..)
994
+ | Rvalue :: NullaryOp ( ..)
995
+ | Rvalue :: UnaryOp ( ..)
996
+ | Rvalue :: Discriminant ( ..)
997
+ | Rvalue :: Aggregate ( ..)
998
+ | Rvalue :: ThreadLocalRef ( ..) => { }
999
+ }
1000
+ }
999
1001
1000
- match terminator. kind {
1001
- TerminatorKind :: Drop { place : dropped_place, .. }
1002
- | TerminatorKind :: DropAndReplace { place : dropped_place, .. } => {
1003
- self . locals . insert ( dropped_place. local ) ;
1004
- }
1002
+ fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
1003
+ self . super_terminator ( terminator, location) ;
1005
1004
1006
- TerminatorKind :: Abort
1007
- | TerminatorKind :: Assert { .. }
1008
- | TerminatorKind :: Call { .. }
1009
- | TerminatorKind :: FalseEdge { .. }
1010
- | TerminatorKind :: FalseUnwind { .. }
1011
- | TerminatorKind :: GeneratorDrop
1012
- | TerminatorKind :: Goto { .. }
1013
- | TerminatorKind :: Resume
1014
- | TerminatorKind :: Return
1015
- | TerminatorKind :: SwitchInt { .. }
1016
- | TerminatorKind :: Unreachable
1017
- | TerminatorKind :: Yield { .. }
1018
- | TerminatorKind :: InlineAsm { .. } => { }
1005
+ match terminator. kind {
1006
+ TerminatorKind :: Drop { place : dropped_place, .. }
1007
+ | TerminatorKind :: DropAndReplace { place : dropped_place, .. } => {
1008
+ self . locals . insert ( dropped_place. local ) ;
1019
1009
}
1010
+
1011
+ TerminatorKind :: Abort
1012
+ | TerminatorKind :: Assert { .. }
1013
+ | TerminatorKind :: Call { .. }
1014
+ | TerminatorKind :: FalseEdge { .. }
1015
+ | TerminatorKind :: FalseUnwind { .. }
1016
+ | TerminatorKind :: GeneratorDrop
1017
+ | TerminatorKind :: Goto { .. }
1018
+ | TerminatorKind :: Resume
1019
+ | TerminatorKind :: Return
1020
+ | TerminatorKind :: SwitchInt { .. }
1021
+ | TerminatorKind :: Unreachable
1022
+ | TerminatorKind :: Yield { .. }
1023
+ | TerminatorKind :: InlineAsm { .. } => { }
1020
1024
}
1021
1025
}
1022
-
1023
- let mut visitor = BorrowCollector { locals : BitSet :: new_empty ( body. local_decls . len ( ) ) } ;
1024
- visitor. visit_body ( body) ;
1025
- visitor. locals
1026
1026
}
1027
1027
1028
1028
/// `PlaceElem::Index` only stores a `Local`, so we can't replace that with a full `Place`.
1029
1029
///
1030
1030
/// Collect locals used as indices so we don't generate candidates that are impossible to apply
1031
1031
/// later.
1032
1032
fn locals_used_as_array_index ( body : & Body < ' _ > ) -> BitSet < Local > {
1033
- struct IndexCollector {
1034
- locals : BitSet < Local > ,
1035
- }
1036
-
1037
- impl < ' tcx > Visitor < ' tcx > for IndexCollector {
1038
- fn visit_projection_elem (
1039
- & mut self ,
1040
- local : Local ,
1041
- proj_base : & [ PlaceElem < ' tcx > ] ,
1042
- elem : PlaceElem < ' tcx > ,
1043
- context : PlaceContext ,
1044
- location : Location ,
1045
- ) {
1046
- if let PlaceElem :: Index ( i) = elem {
1047
- self . locals . insert ( i) ;
1048
- }
1049
- self . super_projection_elem ( local, proj_base, elem, context, location) ;
1050
- }
1051
- }
1052
-
1053
1033
let mut visitor = IndexCollector { locals : BitSet :: new_empty ( body. local_decls . len ( ) ) } ;
1054
1034
visitor. visit_body ( body) ;
1055
1035
visitor. locals
1056
1036
}
1037
+
1038
+ struct IndexCollector {
1039
+ locals : BitSet < Local > ,
1040
+ }
1041
+
1042
+ impl < ' tcx > Visitor < ' tcx > for IndexCollector {
1043
+ fn visit_projection_elem (
1044
+ & mut self ,
1045
+ local : Local ,
1046
+ proj_base : & [ PlaceElem < ' tcx > ] ,
1047
+ elem : PlaceElem < ' tcx > ,
1048
+ context : PlaceContext ,
1049
+ location : Location ,
1050
+ ) {
1051
+ if let PlaceElem :: Index ( i) = elem {
1052
+ self . locals . insert ( i) ;
1053
+ }
1054
+ self . super_projection_elem ( local, proj_base, elem, context, location) ;
1055
+ }
1056
+ }
0 commit comments