@@ -800,27 +800,108 @@ enum OffsetSign {
800
800
}
801
801
802
802
struct Offset {
803
- value : String ,
803
+ value : MinifyingSugg < ' static > ,
804
804
sign : OffsetSign ,
805
805
}
806
806
807
807
impl Offset {
808
- fn negative ( value : String ) -> Self {
808
+ fn negative ( value : MinifyingSugg < ' static > ) -> Self {
809
809
Self {
810
810
value,
811
811
sign : OffsetSign :: Negative ,
812
812
}
813
813
}
814
814
815
- fn positive ( value : String ) -> Self {
815
+ fn positive ( value : MinifyingSugg < ' static > ) -> Self {
816
816
Self {
817
817
value,
818
818
sign : OffsetSign :: Positive ,
819
819
}
820
820
}
821
821
822
822
fn empty ( ) -> Self {
823
- Self :: positive ( "0" . into ( ) )
823
+ Self :: positive ( MinifyingSugg :: non_paren ( "0" ) )
824
+ }
825
+ }
826
+
827
+ fn apply_offset ( lhs : & MinifyingSugg < ' static > , rhs : & Offset ) -> MinifyingSugg < ' static > {
828
+ match rhs. sign {
829
+ OffsetSign :: Positive => lhs + & rhs. value ,
830
+ OffsetSign :: Negative => lhs - & rhs. value ,
831
+ }
832
+ }
833
+
834
+ #[ derive( Clone ) ]
835
+ struct MinifyingSugg < ' a > ( sugg:: Sugg < ' a > ) ;
836
+
837
+ impl std:: fmt:: Display for MinifyingSugg < ' _ > {
838
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
839
+ std:: fmt:: Display :: fmt ( & self . 0 , f)
840
+ }
841
+ }
842
+
843
+ impl < ' a > MinifyingSugg < ' a > {
844
+ fn as_str ( & self ) -> & str {
845
+ let sugg:: Sugg :: NonParen ( s) | sugg:: Sugg :: MaybeParen ( s) | sugg:: Sugg :: BinOp ( _, s) = & self . 0 ;
846
+ s. as_ref ( )
847
+ }
848
+
849
+ fn hir ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > , default : & ' a str ) -> Self {
850
+ Self ( sugg:: Sugg :: hir ( cx, expr, default) )
851
+ }
852
+
853
+ fn maybe_par ( self ) -> Self {
854
+ Self ( self . 0 . maybe_par ( ) )
855
+ }
856
+
857
+ fn non_paren ( str : impl Into < std:: borrow:: Cow < ' a , str > > ) -> Self {
858
+ Self ( sugg:: Sugg :: NonParen ( str. into ( ) ) )
859
+ }
860
+ }
861
+
862
+ impl std:: ops:: Add for & MinifyingSugg < ' static > {
863
+ type Output = MinifyingSugg < ' static > ;
864
+ fn add ( self , rhs : & MinifyingSugg < ' static > ) -> MinifyingSugg < ' static > {
865
+ match ( self . as_str ( ) , rhs. as_str ( ) ) {
866
+ ( "0" , _) => rhs. clone ( ) ,
867
+ ( _, "0" ) => self . clone ( ) ,
868
+ ( _, _) => MinifyingSugg ( & self . 0 + & rhs. 0 ) ,
869
+ }
870
+ }
871
+ }
872
+
873
+ impl std:: ops:: Sub for & MinifyingSugg < ' static > {
874
+ type Output = MinifyingSugg < ' static > ;
875
+ fn sub ( self , rhs : & MinifyingSugg < ' static > ) -> MinifyingSugg < ' static > {
876
+ match ( self . as_str ( ) , rhs. as_str ( ) ) {
877
+ ( _, "0" ) => self . clone ( ) ,
878
+ ( "0" , _) => MinifyingSugg ( sugg:: make_unop ( "-" , rhs. 0 . clone ( ) ) ) ,
879
+ ( x, y) if x == y => MinifyingSugg :: non_paren ( "0" ) ,
880
+ ( _, _) => MinifyingSugg ( & self . 0 - & rhs. 0 ) ,
881
+ }
882
+ }
883
+ }
884
+
885
+ impl std:: ops:: Add < & MinifyingSugg < ' static > > for MinifyingSugg < ' static > {
886
+ type Output = MinifyingSugg < ' static > ;
887
+ fn add ( self , rhs : & MinifyingSugg < ' static > ) -> MinifyingSugg < ' static > {
888
+ match ( self . as_str ( ) , rhs. as_str ( ) ) {
889
+ ( "0" , _) => rhs. clone ( ) ,
890
+ ( _, "0" ) => self ,
891
+ ( _, _) => MinifyingSugg ( self . 0 + & rhs. 0 ) ,
892
+ }
893
+ }
894
+ }
895
+
896
+ impl std:: ops:: Sub < & MinifyingSugg < ' static > > for MinifyingSugg < ' static > {
897
+ type Output = MinifyingSugg < ' static > ;
898
+ fn sub ( self , rhs : & MinifyingSugg < ' static > ) -> MinifyingSugg < ' static > {
899
+ match ( self . as_str ( ) , rhs. as_str ( ) ) {
900
+ ( _, "0" ) => self ,
901
+ ( "0" , _) => MinifyingSugg ( sugg:: make_unop ( "-" , rhs. 0 . clone ( ) ) ) ,
902
+ ( x, y) if x == y => MinifyingSugg :: non_paren ( "0" ) ,
903
+ ( _, _) => MinifyingSugg ( self . 0 - & rhs. 0 ) ,
904
+ }
824
905
}
825
906
}
826
907
@@ -878,14 +959,15 @@ fn get_offset<'tcx>(
878
959
cx : & LateContext < ' tcx > ,
879
960
e : & Expr < ' _ > ,
880
961
starts : & [ Start < ' tcx > ] ,
881
- ) -> Option < String > {
962
+ ) -> Option < MinifyingSugg < ' static > > {
882
963
match & e. kind {
883
964
ExprKind :: Lit ( l) => match l. node {
884
- ast:: LitKind :: Int ( x, _ty) => Some ( x. to_string ( ) ) ,
965
+ ast:: LitKind :: Int ( x, _ty) => Some ( MinifyingSugg :: non_paren ( x. to_string ( ) ) ) ,
885
966
_ => None ,
886
967
} ,
887
968
ExprKind :: Path ( ..) if extract_start ( cx, e, starts) . is_none ( ) => {
888
- Some ( snippet_opt ( cx, e. span ) . unwrap_or_else ( || "??" . into ( ) ) )
969
+ // `e` is always non paren as it's a `Path`
970
+ Some ( MinifyingSugg :: non_paren ( snippet ( cx, e. span , "???" ) ) )
889
971
} ,
890
972
_ => None ,
891
973
}
@@ -979,75 +1061,88 @@ fn build_manual_memcpy_suggestion<'tcx>(
979
1061
dst : IndexExpr < ' _ > ,
980
1062
src : IndexExpr < ' _ > ,
981
1063
) -> String {
982
- fn print_sum ( arg1 : & str , arg2 : & Offset ) -> String {
983
- match ( arg1, & arg2. value [ ..] , arg2. sign ) {
984
- ( "0" , "0" , _) => "0" . into ( ) ,
985
- ( "0" , x, OffsetSign :: Positive ) | ( x, "0" , _) => x. into ( ) ,
986
- ( "0" , x, OffsetSign :: Negative ) => format ! ( "-{}" , x) ,
987
- ( x, y, OffsetSign :: Positive ) => format ! ( "({} + {})" , x, y) ,
988
- ( x, y, OffsetSign :: Negative ) => {
989
- if x == y {
990
- "0" . into ( )
991
- } else {
992
- format ! ( "({} - {})" , x, y)
993
- }
994
- } ,
995
- }
996
- }
997
-
998
- fn print_offset ( start_str : & str , inline_offset : & Offset ) -> String {
999
- let offset = print_sum ( start_str, inline_offset) ;
1064
+ fn print_offset ( offset : MinifyingSugg < ' static > ) -> MinifyingSugg < ' static > {
1000
1065
if offset. as_str ( ) == "0" {
1001
- "" . into ( )
1066
+ MinifyingSugg :: non_paren ( "" )
1002
1067
} else {
1003
1068
offset
1004
1069
}
1005
1070
}
1006
1071
1007
- let print_limit = |end : & Expr < ' _ > , offset : Offset , base : & Expr < ' _ > | {
1072
+ let print_limit = |end : & Expr < ' _ > , end_str : & str , base : & Expr < ' _ > , sugg : MinifyingSugg < ' static > | -> MinifyingSugg < ' static > {
1008
1073
if_chain ! {
1009
1074
if let ExprKind :: MethodCall ( method, _, len_args, _) = end. kind;
1010
1075
if method. ident. name == sym!( len) ;
1011
1076
if len_args. len( ) == 1 ;
1012
1077
if let Some ( arg) = len_args. get( 0 ) ;
1013
1078
if var_def_id( cx, arg) == var_def_id( cx, base) ;
1014
1079
then {
1015
- match offset. sign {
1016
- OffsetSign :: Negative => format!( "({} - {})" , snippet( cx, end. span, "<src>.len()" ) , offset. value) ,
1017
- OffsetSign :: Positive => "" . into( ) ,
1080
+ if sugg. as_str( ) == end_str {
1081
+ MinifyingSugg :: non_paren( "" )
1082
+ } else {
1083
+ sugg
1018
1084
}
1019
1085
} else {
1020
- let end_str = match limits {
1086
+ match limits {
1021
1087
ast:: RangeLimits :: Closed => {
1022
- let end = sugg:: Sugg :: hir( cx, end, "<count>" ) ;
1023
- format!( "{}" , end + sugg:: ONE )
1088
+ sugg + & MinifyingSugg :: non_paren( "1" )
1024
1089
} ,
1025
- ast:: RangeLimits :: HalfOpen => format!( "{}" , snippet( cx, end. span, ".." ) ) ,
1026
- } ;
1027
-
1028
- print_sum( & end_str, & offset)
1090
+ ast:: RangeLimits :: HalfOpen => sugg,
1091
+ }
1029
1092
}
1030
1093
}
1031
1094
} ;
1032
1095
1033
- let start_str = snippet ( cx, start. span , "" ) . to_string ( ) ;
1034
- let dst_offset = print_offset ( & start_str, & dst. idx_offset ) ;
1035
- let dst_limit = print_limit ( end, dst. idx_offset , dst. base ) ;
1036
- let src_offset = print_offset ( & start_str, & src. idx_offset ) ;
1037
- let src_limit = print_limit ( end, src. idx_offset , src. base ) ;
1096
+ let start_str = MinifyingSugg :: hir ( cx, start, "" ) ;
1097
+ let end_str = MinifyingSugg :: hir ( cx, end, "" ) ;
1098
+
1099
+ let print_offset_and_limit = |idx_expr : & IndexExpr < ' _ > | match idx_expr. idx {
1100
+ StartKind :: Range => (
1101
+ print_offset ( apply_offset ( & start_str, & idx_expr. idx_offset ) ) ,
1102
+ print_limit (
1103
+ end,
1104
+ end_str. as_str ( ) ,
1105
+ idx_expr. base ,
1106
+ apply_offset ( & end_str, & idx_expr. idx_offset ) ,
1107
+ ) ,
1108
+ ) ,
1109
+ StartKind :: Counter { initializer } => {
1110
+ let counter_start = MinifyingSugg :: hir ( cx, initializer, "" ) ;
1111
+ (
1112
+ print_offset ( apply_offset ( & counter_start, & idx_expr. idx_offset ) ) ,
1113
+ print_limit (
1114
+ end,
1115
+ end_str. as_str ( ) ,
1116
+ idx_expr. base ,
1117
+ apply_offset ( & end_str, & idx_expr. idx_offset ) + & counter_start - & start_str,
1118
+ ) ,
1119
+ )
1120
+ } ,
1121
+ } ;
1122
+
1123
+ let ( dst_offset, dst_limit) = print_offset_and_limit ( & dst) ;
1124
+ let ( src_offset, src_limit) = print_offset_and_limit ( & src) ;
1038
1125
1039
1126
let dst_base_str = snippet_opt ( cx, dst. base . span ) . unwrap_or_else ( || "???" . into ( ) ) ;
1040
1127
let src_base_str = snippet_opt ( cx, src. base . span ) . unwrap_or_else ( || "???" . into ( ) ) ;
1041
1128
1042
- let dst = if dst_offset == "" && dst_limit == "" {
1129
+ let dst = if dst_offset. as_str ( ) == "" && dst_limit. as_str ( ) == "" {
1043
1130
dst_base_str
1044
1131
} else {
1045
- format ! ( "{}[{}..{}]" , dst_base_str, dst_offset, dst_limit)
1132
+ format ! (
1133
+ "{}[{}..{}]" ,
1134
+ dst_base_str,
1135
+ dst_offset. maybe_par( ) ,
1136
+ dst_limit. maybe_par( )
1137
+ )
1046
1138
} ;
1047
1139
1048
1140
format ! (
1049
1141
"{}.clone_from_slice(&{}[{}..{}])" ,
1050
- dst, src_base_str, src_offset, src_limit
1142
+ dst,
1143
+ src_base_str,
1144
+ src_offset. maybe_par( ) ,
1145
+ src_limit. maybe_par( )
1051
1146
)
1052
1147
}
1053
1148
0 commit comments