@@ -63,8 +63,8 @@ use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldabl
63
63
64
64
use errors:: { Applicability , DiagnosticBuilder , DiagnosticStyledString } ;
65
65
use rustc_error_codes:: * ;
66
+ use rustc_target:: spec:: abi;
66
67
use syntax_pos:: { Pos , Span } ;
67
-
68
68
use std:: { cmp, fmt} ;
69
69
70
70
mod note;
@@ -766,7 +766,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
766
766
if len > 0 && i != len - 1 {
767
767
value. push_normal ( ", " ) ;
768
768
}
769
- //self.push_comma(&mut value, &mut other_value, len, i);
770
769
}
771
770
if len > 0 {
772
771
value. push_highlighted ( ">" ) ;
@@ -868,6 +867,120 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
868
867
substs. truncate_to ( self . tcx , & generics)
869
868
}
870
869
870
+ /// Given two `fn` signatures highlight only sub-parts that are different.
871
+ fn cmp_fn_sig (
872
+ & self ,
873
+ sig1 : & ty:: PolyFnSig < ' tcx > ,
874
+ sig2 : & ty:: PolyFnSig < ' tcx > ,
875
+ ) -> ( DiagnosticStyledString , DiagnosticStyledString ) {
876
+ let get_lifetimes = |sig| {
877
+ use crate :: hir:: def:: Namespace ;
878
+ let mut s = String :: new ( ) ;
879
+ let ( _, ( sig, reg) ) = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS )
880
+ . name_all_regions ( sig)
881
+ . unwrap ( ) ;
882
+ let lts: Vec < String > = reg. into_iter ( ) . map ( |( _, kind) | kind. to_string ( ) ) . collect ( ) ;
883
+ ( if lts. is_empty ( ) {
884
+ String :: new ( )
885
+ } else {
886
+ format ! ( "for<{}> " , lts. join( ", " ) )
887
+ } , sig)
888
+ } ;
889
+
890
+ let ( lt1, sig1) = get_lifetimes ( sig1) ;
891
+ let ( lt2, sig2) = get_lifetimes ( sig2) ;
892
+
893
+ // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
894
+ let mut values = (
895
+ DiagnosticStyledString :: normal ( "" . to_string ( ) ) ,
896
+ DiagnosticStyledString :: normal ( "" . to_string ( ) ) ,
897
+ ) ;
898
+
899
+ // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
900
+ // ^^^^^^
901
+ values. 0 . push ( sig1. unsafety . prefix_str ( ) , sig1. unsafety != sig2. unsafety ) ;
902
+ values. 1 . push ( sig2. unsafety . prefix_str ( ) , sig1. unsafety != sig2. unsafety ) ;
903
+
904
+ // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
905
+ // ^^^^^^^^^^
906
+ if sig1. abi != abi:: Abi :: Rust {
907
+ values. 0 . push ( format ! ( "extern {} " , sig1. abi) , sig1. abi != sig2. abi ) ;
908
+ }
909
+ if sig2. abi != abi:: Abi :: Rust {
910
+ values. 1 . push ( format ! ( "extern {} " , sig2. abi) , sig1. abi != sig2. abi ) ;
911
+ }
912
+
913
+ // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
914
+ // ^^^^^^^^
915
+ let lifetime_diff = lt1 != lt2;
916
+ values. 0 . push ( lt1, lifetime_diff) ;
917
+ values. 1 . push ( lt2, lifetime_diff) ;
918
+
919
+ // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
920
+ // ^^^
921
+ values. 0 . push_normal ( "fn(" ) ;
922
+ values. 1 . push_normal ( "fn(" ) ;
923
+
924
+ // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
925
+ // ^^^^^
926
+ let len1 = sig1. inputs ( ) . len ( ) ;
927
+ let len2 = sig2. inputs ( ) . len ( ) ;
928
+ if len1 == len2 {
929
+ for ( i, ( l, r) ) in sig1. inputs ( ) . iter ( ) . zip ( sig2. inputs ( ) . iter ( ) ) . enumerate ( ) {
930
+ let ( x1, x2) = self . cmp ( l, r) ;
931
+ ( values. 0 ) . 0 . extend ( x1. 0 ) ;
932
+ ( values. 1 ) . 0 . extend ( x2. 0 ) ;
933
+ self . push_comma ( & mut values. 0 , & mut values. 1 , len1, i) ;
934
+ }
935
+ } else {
936
+ for ( i, l) in sig1. inputs ( ) . iter ( ) . enumerate ( ) {
937
+ values. 0 . push_highlighted ( l. to_string ( ) ) ;
938
+ if i != len1 - 1 {
939
+ values. 0 . push_highlighted ( ", " ) ;
940
+ }
941
+ }
942
+ for ( i, r) in sig2. inputs ( ) . iter ( ) . enumerate ( ) {
943
+ values. 1 . push_highlighted ( r. to_string ( ) ) ;
944
+ if i != len2 - 1 {
945
+ values. 1 . push_highlighted ( ", " ) ;
946
+ }
947
+ }
948
+ }
949
+
950
+ if sig1. c_variadic {
951
+ if len1 > 0 {
952
+ values. 0 . push_normal ( ", " ) ;
953
+ }
954
+ values. 0 . push ( "..." , !sig2. c_variadic ) ;
955
+ }
956
+ if sig2. c_variadic {
957
+ if len2 > 0 {
958
+ values. 1 . push_normal ( ", " ) ;
959
+ }
960
+ values. 1 . push ( "..." , !sig1. c_variadic ) ;
961
+ }
962
+
963
+ // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
964
+ // ^
965
+ values. 0 . push_normal ( ")" ) ;
966
+ values. 1 . push_normal ( ")" ) ;
967
+
968
+ // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
969
+ // ^^^^^^^^
970
+ let output1 = sig1. output ( ) ;
971
+ let output2 = sig2. output ( ) ;
972
+ let ( x1, x2) = self . cmp ( output1, output2) ;
973
+ if !output1. is_unit ( ) {
974
+ values. 0 . push_normal ( " -> " ) ;
975
+ ( values. 0 ) . 0 . extend ( x1. 0 ) ;
976
+ }
977
+ if !output2. is_unit ( ) {
978
+ values. 1 . push_normal ( " -> " ) ;
979
+ ( values. 1 ) . 0 . extend ( x2. 0 ) ;
980
+ }
981
+ values
982
+ }
983
+
871
984
/// Compares two given types, eliding parts that are the same between them and highlighting
872
985
/// relevant differences, and return two representation of those types for highlighted printing.
873
986
fn cmp ( & self , t1 : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> ( DiagnosticStyledString , DiagnosticStyledString ) {
@@ -968,7 +1081,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
968
1081
for ( i, lifetimes) in lifetimes. enumerate ( ) {
969
1082
let l1 = lifetime_display ( lifetimes. 0 ) ;
970
1083
let l2 = lifetime_display ( lifetimes. 1 ) ;
971
- if l1 == l2 {
1084
+ if lifetimes . 0 == lifetimes . 1 {
972
1085
values. 0 . push_normal ( "'_" ) ;
973
1086
values. 1 . push_normal ( "'_" ) ;
974
1087
} else {
@@ -1124,6 +1237,64 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1124
1237
values
1125
1238
}
1126
1239
1240
+ // When encountering tuples of the same size, highlight only the differing types
1241
+ ( & ty:: Tuple ( substs1) , & ty:: Tuple ( substs2) ) if substs1. len ( ) == substs2. len ( ) => {
1242
+ let mut values = (
1243
+ DiagnosticStyledString :: normal ( "(" ) ,
1244
+ DiagnosticStyledString :: normal ( "(" ) ,
1245
+ ) ;
1246
+ let len = substs1. len ( ) ;
1247
+ for ( i, ( left, right) ) in substs1. types ( ) . zip ( substs2. types ( ) ) . enumerate ( ) {
1248
+ let ( x1, x2) = self . cmp ( left, right) ;
1249
+ ( values. 0 ) . 0 . extend ( x1. 0 ) ;
1250
+ ( values. 1 ) . 0 . extend ( x2. 0 ) ;
1251
+ self . push_comma ( & mut values. 0 , & mut values. 1 , len, i) ;
1252
+ }
1253
+ if len == 1 { // Keep the output for single element tuples as `(ty,)`.
1254
+ values. 0 . push_normal ( "," ) ;
1255
+ values. 1 . push_normal ( "," ) ;
1256
+ }
1257
+ values. 0 . push_normal ( ")" ) ;
1258
+ values. 1 . push_normal ( ")" ) ;
1259
+ values
1260
+ }
1261
+
1262
+ ( ty:: FnDef ( did1, substs1) , ty:: FnDef ( did2, substs2) ) => {
1263
+ let sig1 = self . tcx . fn_sig ( * did1) . subst ( self . tcx , substs1) ;
1264
+ let sig2 = self . tcx . fn_sig ( * did2) . subst ( self . tcx , substs2) ;
1265
+ let mut values = self . cmp_fn_sig ( & sig1, & sig2) ;
1266
+ let path1 = format ! ( " {{{}}}" , self . tcx. def_path_str_with_substs( * did1, substs1) ) ;
1267
+ let path2 = format ! ( " {{{}}}" , self . tcx. def_path_str_with_substs( * did2, substs2) ) ;
1268
+ let same_path = path1 == path2;
1269
+ values. 0 . push ( path1, !same_path) ;
1270
+ values. 1 . push ( path2, !same_path) ;
1271
+ values
1272
+ }
1273
+
1274
+ ( ty:: FnDef ( did1, substs1) , ty:: FnPtr ( sig2) ) => {
1275
+ let sig1 = self . tcx . fn_sig ( * did1) . subst ( self . tcx , substs1) ;
1276
+ let mut values = self . cmp_fn_sig ( & sig1, sig2) ;
1277
+ values. 0 . push_normal ( format ! (
1278
+ " {{{}}}" ,
1279
+ self . tcx. def_path_str_with_substs( * did1, substs1) ) ,
1280
+ ) ;
1281
+ values
1282
+ }
1283
+
1284
+ ( ty:: FnPtr ( sig1) , ty:: FnDef ( did2, substs2) ) => {
1285
+ let sig2 = self . tcx . fn_sig ( * did2) . subst ( self . tcx , substs2) ;
1286
+ let mut values = self . cmp_fn_sig ( sig1, & sig2) ;
1287
+ values. 1 . push_normal ( format ! (
1288
+ " {{{}}}" ,
1289
+ self . tcx. def_path_str_with_substs( * did2, substs2) ) ,
1290
+ ) ;
1291
+ values
1292
+ }
1293
+
1294
+ ( ty:: FnPtr ( sig1) , ty:: FnPtr ( sig2) ) => {
1295
+ self . cmp_fn_sig ( sig1, sig2)
1296
+ }
1297
+
1127
1298
_ => {
1128
1299
if t1 == t2 {
1129
1300
// The two types are the same, elide and don't highlight.
0 commit comments