@@ -858,98 +858,98 @@ fn find_candidates<'a, 'tcx>(
858858 tcx : TyCtxt < ' tcx > ,
859859 body : & ' a Body < ' tcx > ,
860860) -> 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+ }
868871
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+ }
880879
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+ }
885891
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+ }
890896
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+ }
900901
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+ }
902911
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" ) ;
907913
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 ;
915925 }
926+ }
916927
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.
921937 return ;
922938 }
923- for elem in dest. projection {
924- if let PlaceElem :: Index ( _) = elem {
925- // `dest` contains an indexing projection.
926- return ;
927- }
928939
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 ;
933943 }
934-
935- self . candidates . push ( CandidateAssignment {
936- dest : * dest,
937- src : src. local ,
938- loc : location,
939- } ) ;
940944 }
945+
946+ self . candidates . push ( CandidateAssignment {
947+ dest : * dest,
948+ src : src. local ,
949+ loc : location,
950+ } ) ;
941951 }
942952 }
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
953953}
954954
955955/// 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 {
965965
966966/// Walks MIR to find all locals that have their address taken anywhere.
967967fn 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+ }
971972
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+ }
975976
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) ;
982980
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+ }
994986 }
995- }
996987
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+ }
9991001
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) ;
10051004
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 ) ;
10191009 }
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 { .. } => { }
10201024 }
10211025 }
1022-
1023- let mut visitor = BorrowCollector { locals : BitSet :: new_empty ( body. local_decls . len ( ) ) } ;
1024- visitor. visit_body ( body) ;
1025- visitor. locals
10261026}
10271027
10281028/// `PlaceElem::Index` only stores a `Local`, so we can't replace that with a full `Place`.
10291029///
10301030/// Collect locals used as indices so we don't generate candidates that are impossible to apply
10311031/// later.
10321032fn 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-
10531033 let mut visitor = IndexCollector { locals : BitSet :: new_empty ( body. local_decls . len ( ) ) } ;
10541034 visitor. visit_body ( body) ;
10551035 visitor. locals
10561036}
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