@@ -717,53 +717,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
717717 value : & mut DiagStyledString ,
718718 other_value : & mut DiagStyledString ,
719719 name : String ,
720- sub : ty:: GenericArgsRef < ' tcx > ,
720+ args : & [ ty:: GenericArg < ' tcx > ] ,
721721 pos : usize ,
722722 other_ty : Ty < ' tcx > ,
723723 ) {
724724 // `value` and `other_value` hold two incomplete type representation for display.
725725 // `name` is the path of both types being compared. `sub`
726726 value. push_highlighted ( name) ;
727- let len = sub. len ( ) ;
728- if len > 0 {
729- value. push_highlighted ( "<" ) ;
730- }
731727
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 ;
747730 }
731+ value. push_highlighted ( "<" ) ;
748732
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 ( ", " ) ;
758736 }
759737
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+ }
762757 }
763758 }
764- if len > 0 {
765- value. push_highlighted ( ">" ) ;
766- }
759+
760+ value. push_highlighted ( ">" ) ;
767761 }
768762
769763 /// 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> {
791785 t1_out : & mut DiagStyledString ,
792786 t2_out : & mut DiagStyledString ,
793787 path : String ,
794- sub : & ' tcx [ ty:: GenericArg < ' tcx > ] ,
788+ args : & ' tcx [ ty:: GenericArg < ' tcx > ] ,
795789 other_path : String ,
796790 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+ }
811804 }
812805 }
813806 }
814- None
807+ false
815808 }
816809
817810 /// Adds a `,` to the type representation only if it is appropriate.
818811 fn push_comma (
819812 & self ,
820813 value : & mut DiagStyledString ,
821814 other_value : & mut DiagStyledString ,
822- len : usize ,
823815 pos : usize ,
824816 ) {
825- if len > 0 && pos != len - 1 {
817+ if pos > 0 {
826818 value. push_normal ( ", " ) ;
827819 other_value. push_normal ( ", " ) ;
828820 }
@@ -899,10 +891,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
899891 let len2 = sig2. inputs ( ) . len ( ) ;
900892 if len1 == len2 {
901893 for ( i, ( l, r) ) in iter:: zip ( sig1. inputs ( ) , sig2. inputs ( ) ) . enumerate ( ) {
894+ self . push_comma ( & mut values. 0 , & mut values. 1 , i) ;
902895 let ( x1, x2) = self . cmp ( * l, * r) ;
903896 ( values. 0 ) . 0 . extend ( x1. 0 ) ;
904897 ( values. 1 ) . 0 . extend ( x2. 0 ) ;
905- self . push_comma ( & mut values. 0 , & mut values. 1 , len1, i) ;
906898 }
907899 } else {
908900 for ( i, l) in sig1. inputs ( ) . iter ( ) . enumerate ( ) {
@@ -1150,14 +1142,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11501142 let len1 = sub_no_defaults_1. len ( ) ;
11511143 let len2 = sub_no_defaults_2. len ( ) ;
11521144 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.. ] ;
11551147 let common_default_params =
11561148 iter:: zip ( remainder1. iter ( ) . rev ( ) , remainder2. iter ( ) . rev ( ) )
11571149 . filter ( |( a, b) | a == b)
11581150 . count ( ) ;
11591151 let len = sub1. len ( ) - common_default_params;
1160- let consts_offset = len - sub1. consts ( ) . count ( ) ;
11611152
11621153 // Only draw `<...>` if there are lifetime/type arguments.
11631154 if len > 0 {
@@ -1169,70 +1160,68 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11691160 let s = lifetime. to_string ( ) ;
11701161 if s. is_empty ( ) { "'_" . to_string ( ) } else { s }
11711162 }
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- }
12041163
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+ }
12211220 }
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) ;
12321221 }
12331222
12341223 // Close the type argument bracket.
1235- // Only draw `<...>` if there are lifetime/type arguments.
1224+ // Only draw `<...>` if there are arguments.
12361225 if len > 0 {
12371226 values. 0 . push_normal ( ">" ) ;
12381227 values. 1 . push_normal ( ">" ) ;
@@ -1244,35 +1233,29 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
12441233 // Foo<Bar<Qux>
12451234 // ------- this type argument is exactly the same as the other type
12461235 // 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+ ) {
12581244 return values;
12591245 }
12601246 // Check for case:
12611247 // let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
12621248 // Bar<Qux>
12631249 // Foo<Bar<Qux>>
12641250 // ------- 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+ ) {
12761259 return values;
12771260 }
12781261
@@ -1343,8 +1326,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
13431326 let mut values = ( DiagStyledString :: normal ( "(" ) , DiagStyledString :: normal ( "(" ) ) ;
13441327 let len = args1. len ( ) ;
13451328 for ( i, ( left, right) ) in args1. iter ( ) . zip ( args2) . enumerate ( ) {
1329+ self . push_comma ( & mut values. 0 , & mut values. 1 , i) ;
13461330 recurse ( left, right, & mut values) ;
1347- self . push_comma ( & mut values. 0 , & mut values. 1 , len, i) ;
13481331 }
13491332 if len == 1 {
13501333 // Keep the output for single element tuples as `(ty,)`.
0 commit comments