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