@@ -717,51 +717,46 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
717
717
value : & mut DiagStyledString ,
718
718
other_value : & mut DiagStyledString ,
719
719
name : String ,
720
- sub : ty:: GenericArgsRef < ' tcx > ,
720
+ args : & [ ty:: GenericArg < ' tcx > ] ,
721
721
pos : usize ,
722
722
other_ty : Ty < ' tcx > ,
723
723
) {
724
724
// `value` and `other_value` hold two incomplete type representation for display.
725
725
// `name` is the path of both types being compared. `sub`
726
726
value. push_highlighted ( name) ;
727
- let len = sub. len ( ) ;
728
- if len > 0 {
729
- value. push_highlighted ( "<" ) ;
730
- }
731
727
732
- // Output the lifetimes for the first type
733
- let lifetimes = sub
734
- . regions ( )
735
- . map ( |lifetime| {
736
- let s = lifetime. to_string ( ) ;
737
- if s. is_empty ( ) { "'_" . to_string ( ) } else { s }
738
- } )
739
- . collect :: < Vec < _ > > ( )
740
- . join ( ", " ) ;
741
- if !lifetimes. is_empty ( ) {
742
- if sub. regions ( ) . count ( ) < len {
743
- value. push_normal ( lifetimes + ", " ) ;
744
- } else {
745
- value. push_normal ( lifetimes) ;
746
- }
728
+ if !args. is_empty ( ) {
729
+ value. push_highlighted ( "<" ) ;
747
730
}
748
731
749
- // Highlight all the type arguments that aren't at `pos` and compare the type argument at
750
- // `pos` and `other_ty`.
751
- for ( i, type_arg) in sub. types ( ) . enumerate ( ) {
752
- if i == pos {
753
- let values = self . cmp ( type_arg, other_ty) ;
754
- value. 0 . extend ( ( values. 0 ) . 0 ) ;
755
- other_value. 0 . extend ( ( values. 1 ) . 0 ) ;
756
- } else {
757
- value. push_highlighted ( type_arg. to_string ( ) ) ;
732
+ for ( i, arg) in args. iter ( ) . enumerate ( ) {
733
+ if i > 0 {
734
+ value. push_normal ( ", " ) ;
758
735
}
759
736
760
- if len > 0 && i != len - 1 {
761
- value. push_normal ( ", " ) ;
737
+ match arg. unpack ( ) {
738
+ ty:: GenericArgKind :: Lifetime ( lt) => {
739
+ let s = lt. to_string ( ) ;
740
+ value. push_normal ( if s. is_empty ( ) { "'_" } else { & s } ) ;
741
+ }
742
+ ty:: GenericArgKind :: Const ( ct) => {
743
+ value. push_normal ( ct. to_string ( ) ) ;
744
+ }
745
+ // Highlight all the type arguments that aren't at `pos` and compare
746
+ // the type argument at `pos` and `other_ty`.
747
+ ty:: GenericArgKind :: Type ( type_arg) => {
748
+ if i == pos {
749
+ let values = self . cmp ( type_arg, other_ty) ;
750
+ value. 0 . extend ( ( values. 0 ) . 0 ) ;
751
+ other_value. 0 . extend ( ( values. 1 ) . 0 ) ;
752
+ } else {
753
+ value. push_highlighted ( type_arg. to_string ( ) ) ;
754
+ }
755
+ }
762
756
}
763
757
}
764
- if len > 0 {
758
+
759
+ if !args. is_empty ( ) {
765
760
value. push_highlighted ( ">" ) ;
766
761
}
767
762
}
@@ -791,38 +786,36 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
791
786
t1_out : & mut DiagStyledString ,
792
787
t2_out : & mut DiagStyledString ,
793
788
path : String ,
794
- sub : & ' tcx [ ty:: GenericArg < ' tcx > ] ,
789
+ args : & ' tcx [ ty:: GenericArg < ' tcx > ] ,
795
790
other_path : String ,
796
791
other_ty : Ty < ' tcx > ,
797
- ) -> Option < ( ) > {
798
- // FIXME/HACK: Go back to `GenericArgsRef` to use its inherent methods,
799
- // ideally that shouldn't be necessary.
800
- let sub = self . tcx . mk_args ( sub) ;
801
- for ( i, ta) in sub. types ( ) . enumerate ( ) {
802
- if ta == other_ty {
803
- self . highlight_outer ( t1_out, t2_out, path, sub, i, other_ty) ;
804
- return Some ( ( ) ) ;
805
- }
806
- if let ty:: Adt ( def, _) = ta. kind ( ) {
807
- let path_ = self . tcx . def_path_str ( def. did ( ) ) ;
808
- if path_ == other_path {
809
- self . highlight_outer ( t1_out, t2_out, path, sub, i, other_ty) ;
810
- return Some ( ( ) ) ;
792
+ ) -> bool {
793
+ for ( i, arg) in args. iter ( ) . enumerate ( ) {
794
+ if let Some ( ta) = arg. as_type ( ) {
795
+ if ta == other_ty {
796
+ self . highlight_outer ( t1_out, t2_out, path, args, i, other_ty) ;
797
+ return true ;
798
+ }
799
+ if let ty:: Adt ( def, _) = ta. kind ( ) {
800
+ let path_ = self . tcx . def_path_str ( def. did ( ) ) ;
801
+ if path_ == other_path {
802
+ self . highlight_outer ( t1_out, t2_out, path, args, i, other_ty) ;
803
+ return true ;
804
+ }
811
805
}
812
806
}
813
807
}
814
- None
808
+ false
815
809
}
816
810
817
811
/// Adds a `,` to the type representation only if it is appropriate.
818
812
fn push_comma (
819
813
& self ,
820
814
value : & mut DiagStyledString ,
821
815
other_value : & mut DiagStyledString ,
822
- len : usize ,
823
816
pos : usize ,
824
817
) {
825
- if len > 0 && pos != len - 1 {
818
+ if pos > 0 {
826
819
value. push_normal ( ", " ) ;
827
820
other_value. push_normal ( ", " ) ;
828
821
}
@@ -899,10 +892,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
899
892
let len2 = sig2. inputs ( ) . len ( ) ;
900
893
if len1 == len2 {
901
894
for ( i, ( l, r) ) in iter:: zip ( sig1. inputs ( ) , sig2. inputs ( ) ) . enumerate ( ) {
895
+ self . push_comma ( & mut values. 0 , & mut values. 1 , i) ;
902
896
let ( x1, x2) = self . cmp ( * l, * r) ;
903
897
( values. 0 ) . 0 . extend ( x1. 0 ) ;
904
898
( values. 1 ) . 0 . extend ( x2. 0 ) ;
905
- self . push_comma ( & mut values. 0 , & mut values. 1 , len1, i) ;
906
899
}
907
900
} else {
908
901
for ( i, l) in sig1. inputs ( ) . iter ( ) . enumerate ( ) {
@@ -1150,14 +1143,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1150
1143
let len1 = sub_no_defaults_1. len ( ) ;
1151
1144
let len2 = sub_no_defaults_2. len ( ) ;
1152
1145
let common_len = cmp:: min ( len1, len2) ;
1153
- let remainder1: Vec < _ > = sub1. types ( ) . skip ( common_len) . collect ( ) ;
1154
- let remainder2: Vec < _ > = sub2. types ( ) . skip ( common_len) . collect ( ) ;
1146
+ let remainder1 = & sub1[ common_len.. ] ;
1147
+ let remainder2 = & sub2[ common_len.. ] ;
1155
1148
let common_default_params =
1156
1149
iter:: zip ( remainder1. iter ( ) . rev ( ) , remainder2. iter ( ) . rev ( ) )
1157
1150
. filter ( |( a, b) | a == b)
1158
1151
. count ( ) ;
1159
1152
let len = sub1. len ( ) - common_default_params;
1160
- let consts_offset = len - sub1. consts ( ) . count ( ) ;
1161
1153
1162
1154
// Only draw `<...>` if there are lifetime/type arguments.
1163
1155
if len > 0 {
@@ -1169,70 +1161,68 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1169
1161
let s = lifetime. to_string ( ) ;
1170
1162
if s. is_empty ( ) { "'_" . to_string ( ) } else { s }
1171
1163
}
1172
- // At one point we'd like to elide all lifetimes here, they are irrelevant for
1173
- // all diagnostics that use this output
1174
- //
1175
- // Foo<'x, '_, Bar>
1176
- // Foo<'y, '_, Qux>
1177
- // ^^ ^^ --- type arguments are not elided
1178
- // | |
1179
- // | elided as they were the same
1180
- // not elided, they were different, but irrelevant
1181
- //
1182
- // For bound lifetimes, keep the names of the lifetimes,
1183
- // even if they are the same so that it's clear what's happening
1184
- // if we have something like
1185
- //
1186
- // for<'r, 's> fn(Inv<'r>, Inv<'s>)
1187
- // for<'r> fn(Inv<'r>, Inv<'r>)
1188
- let lifetimes = sub1. regions ( ) . zip ( sub2. regions ( ) ) ;
1189
- for ( i, lifetimes) in lifetimes. enumerate ( ) {
1190
- let l1 = lifetime_display ( lifetimes. 0 ) ;
1191
- let l2 = lifetime_display ( lifetimes. 1 ) ;
1192
- if lifetimes. 0 != lifetimes. 1 {
1193
- values. 0 . push_highlighted ( l1) ;
1194
- values. 1 . push_highlighted ( l2) ;
1195
- } else if lifetimes. 0 . is_bound ( ) || self . tcx . sess . opts . verbose {
1196
- values. 0 . push_normal ( l1) ;
1197
- values. 1 . push_normal ( l2) ;
1198
- } else {
1199
- values. 0 . push_normal ( "'_" ) ;
1200
- values. 1 . push_normal ( "'_" ) ;
1201
- }
1202
- self . push_comma ( & mut values. 0 , & mut values. 1 , len, i) ;
1203
- }
1204
1164
1205
- // We're comparing two types with the same path, so we compare the type
1206
- // arguments for both. If they are the same, do not highlight and elide from the
1207
- // output.
1208
- // Foo<_, Bar>
1209
- // Foo<_, Qux>
1210
- // ^ elided type as this type argument was the same in both sides
1211
- let type_arguments = sub1. types ( ) . zip ( sub2. types ( ) ) ;
1212
- let regions_len = sub1. regions ( ) . count ( ) ;
1213
- let num_display_types = consts_offset - regions_len;
1214
- for ( i, ( ta1, ta2) ) in type_arguments. take ( num_display_types) . enumerate ( ) {
1215
- let i = i + regions_len;
1216
- if ta1 == ta2 && !self . tcx . sess . opts . verbose {
1217
- values. 0 . push_normal ( "_" ) ;
1218
- values. 1 . push_normal ( "_" ) ;
1219
- } else {
1220
- recurse ( ta1, ta2, & mut values) ;
1165
+ for ( i, ( arg1, arg2) ) in sub1. iter ( ) . zip ( sub2) . enumerate ( ) . take ( len) {
1166
+ self . push_comma ( & mut values. 0 , & mut values. 1 , i) ;
1167
+ match arg1. unpack ( ) {
1168
+ // At one point we'd like to elide all lifetimes here, they are
1169
+ // irrelevant for all diagnostics that use this output.
1170
+ //
1171
+ // Foo<'x, '_, Bar>
1172
+ // Foo<'y, '_, Qux>
1173
+ // ^^ ^^ --- type arguments are not elided
1174
+ // | |
1175
+ // | elided as they were the same
1176
+ // not elided, they were different, but irrelevant
1177
+ //
1178
+ // For bound lifetimes, keep the names of the lifetimes,
1179
+ // even if they are the same so that it's clear what's happening
1180
+ // if we have something like
1181
+ //
1182
+ // for<'r, 's> fn(Inv<'r>, Inv<'s>)
1183
+ // for<'r> fn(Inv<'r>, Inv<'r>)
1184
+ ty:: GenericArgKind :: Lifetime ( l1) => {
1185
+ let l1_str = lifetime_display ( l1) ;
1186
+ let l2 = arg2. expect_region ( ) ;
1187
+ let l2_str = lifetime_display ( l2) ;
1188
+ if l1 != l2 {
1189
+ values. 0 . push_highlighted ( l1_str) ;
1190
+ values. 1 . push_highlighted ( l2_str) ;
1191
+ } else if l1. is_bound ( ) || self . tcx . sess . opts . verbose {
1192
+ values. 0 . push_normal ( l1_str) ;
1193
+ values. 1 . push_normal ( l2_str) ;
1194
+ } else {
1195
+ values. 0 . push_normal ( "'_" ) ;
1196
+ values. 1 . push_normal ( "'_" ) ;
1197
+ }
1198
+ }
1199
+ ty:: GenericArgKind :: Type ( ta1) => {
1200
+ let ta2 = arg2. expect_ty ( ) ;
1201
+ if ta1 == ta2 && !self . tcx . sess . opts . verbose {
1202
+ values. 0 . push_normal ( "_" ) ;
1203
+ values. 1 . push_normal ( "_" ) ;
1204
+ } else {
1205
+ recurse ( ta1, ta2, & mut values) ;
1206
+ }
1207
+ }
1208
+ // We're comparing two types with the same path, so we compare the type
1209
+ // arguments for both. If they are the same, do not highlight and elide
1210
+ // from the output.
1211
+ // Foo<_, Bar>
1212
+ // Foo<_, Qux>
1213
+ // ^ elided type as this type argument was the same in both sides
1214
+
1215
+ // Do the same for const arguments, if they are equal, do not highlight and
1216
+ // elide them from the output.
1217
+ ty:: GenericArgKind :: Const ( ca1) => {
1218
+ let ca2 = arg2. expect_const ( ) ;
1219
+ maybe_highlight ( ca1, ca2, & mut values, self . tcx ) ;
1220
+ }
1221
1221
}
1222
- self . push_comma ( & mut values. 0 , & mut values. 1 , len, i) ;
1223
- }
1224
-
1225
- // Do the same for const arguments, if they are equal, do not highlight and
1226
- // elide them from the output.
1227
- let const_arguments = sub1. consts ( ) . zip ( sub2. consts ( ) ) ;
1228
- for ( i, ( ca1, ca2) ) in const_arguments. enumerate ( ) {
1229
- let i = i + consts_offset;
1230
- maybe_highlight ( ca1, ca2, & mut values, self . tcx ) ;
1231
- self . push_comma ( & mut values. 0 , & mut values. 1 , len, i) ;
1232
1222
}
1233
1223
1234
1224
// Close the type argument bracket.
1235
- // Only draw `<...>` if there are lifetime/type arguments.
1225
+ // Only draw `<...>` if there are arguments.
1236
1226
if len > 0 {
1237
1227
values. 0 . push_normal ( ">" ) ;
1238
1228
values. 1 . push_normal ( ">" ) ;
@@ -1244,35 +1234,29 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1244
1234
// Foo<Bar<Qux>
1245
1235
// ------- this type argument is exactly the same as the other type
1246
1236
// Bar<Qux>
1247
- if self
1248
- . cmp_type_arg (
1249
- & mut values. 0 ,
1250
- & mut values. 1 ,
1251
- path1. clone ( ) ,
1252
- sub_no_defaults_1,
1253
- path2. clone ( ) ,
1254
- t2,
1255
- )
1256
- . is_some ( )
1257
- {
1237
+ if self . cmp_type_arg (
1238
+ & mut values. 0 ,
1239
+ & mut values. 1 ,
1240
+ path1. clone ( ) ,
1241
+ sub_no_defaults_1,
1242
+ path2. clone ( ) ,
1243
+ t2,
1244
+ ) {
1258
1245
return values;
1259
1246
}
1260
1247
// Check for case:
1261
1248
// let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
1262
1249
// Bar<Qux>
1263
1250
// Foo<Bar<Qux>>
1264
1251
// ------- this type argument is exactly the same as the other type
1265
- if self
1266
- . cmp_type_arg (
1267
- & mut values. 1 ,
1268
- & mut values. 0 ,
1269
- path2,
1270
- sub_no_defaults_2,
1271
- path1,
1272
- t1,
1273
- )
1274
- . is_some ( )
1275
- {
1252
+ if self . cmp_type_arg (
1253
+ & mut values. 1 ,
1254
+ & mut values. 0 ,
1255
+ path2,
1256
+ sub_no_defaults_2,
1257
+ path1,
1258
+ t1,
1259
+ ) {
1276
1260
return values;
1277
1261
}
1278
1262
@@ -1343,8 +1327,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1343
1327
let mut values = ( DiagStyledString :: normal ( "(" ) , DiagStyledString :: normal ( "(" ) ) ;
1344
1328
let len = args1. len ( ) ;
1345
1329
for ( i, ( left, right) ) in args1. iter ( ) . zip ( args2) . enumerate ( ) {
1330
+ self . push_comma ( & mut values. 0 , & mut values. 1 , i) ;
1346
1331
recurse ( left, right, & mut values) ;
1347
- self . push_comma ( & mut values. 0 , & mut values. 1 , len, i) ;
1348
1332
}
1349
1333
if len == 1 {
1350
1334
// Keep the output for single element tuples as `(ty,)`.
0 commit comments