@@ -717,51 +717,46 @@ 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+ value. push_highlighted ( "<" ) ;
747730 }
748731
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 ( ", " ) ;
758735 }
759736
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+ }
762756 }
763757 }
764- if len > 0 {
758+
759+ if !args. is_empty ( ) {
765760 value. push_highlighted ( ">" ) ;
766761 }
767762 }
@@ -791,38 +786,36 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
791786 t1_out : & mut DiagStyledString ,
792787 t2_out : & mut DiagStyledString ,
793788 path : String ,
794- sub : & ' tcx [ ty:: GenericArg < ' tcx > ] ,
789+ args : & ' tcx [ ty:: GenericArg < ' tcx > ] ,
795790 other_path : String ,
796791 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+ }
811805 }
812806 }
813807 }
814- None
808+ false
815809 }
816810
817811 /// Adds a `,` to the type representation only if it is appropriate.
818812 fn push_comma (
819813 & self ,
820814 value : & mut DiagStyledString ,
821815 other_value : & mut DiagStyledString ,
822- len : usize ,
823816 pos : usize ,
824817 ) {
825- if len > 0 && pos != len - 1 {
818+ if pos > 0 {
826819 value. push_normal ( ", " ) ;
827820 other_value. push_normal ( ", " ) ;
828821 }
@@ -899,10 +892,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
899892 let len2 = sig2. inputs ( ) . len ( ) ;
900893 if len1 == len2 {
901894 for ( i, ( l, r) ) in iter:: zip ( sig1. inputs ( ) , sig2. inputs ( ) ) . enumerate ( ) {
895+ self . push_comma ( & mut values. 0 , & mut values. 1 , i) ;
902896 let ( x1, x2) = self . cmp ( * l, * r) ;
903897 ( values. 0 ) . 0 . extend ( x1. 0 ) ;
904898 ( values. 1 ) . 0 . extend ( x2. 0 ) ;
905- self . push_comma ( & mut values. 0 , & mut values. 1 , len1, i) ;
906899 }
907900 } else {
908901 for ( i, l) in sig1. inputs ( ) . iter ( ) . enumerate ( ) {
@@ -1150,14 +1143,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11501143 let len1 = sub_no_defaults_1. len ( ) ;
11511144 let len2 = sub_no_defaults_2. len ( ) ;
11521145 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.. ] ;
11551148 let common_default_params =
11561149 iter:: zip ( remainder1. iter ( ) . rev ( ) , remainder2. iter ( ) . rev ( ) )
11571150 . filter ( |( a, b) | a == b)
11581151 . count ( ) ;
11591152 let len = sub1. len ( ) - common_default_params;
1160- let consts_offset = len - sub1. consts ( ) . count ( ) ;
11611153
11621154 // Only draw `<...>` if there are lifetime/type arguments.
11631155 if len > 0 {
@@ -1169,70 +1161,68 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11691161 let s = lifetime. to_string ( ) ;
11701162 if s. is_empty ( ) { "'_" . to_string ( ) } else { s }
11711163 }
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- }
12041164
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+ }
12211221 }
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) ;
12321222 }
12331223
12341224 // Close the type argument bracket.
1235- // Only draw `<...>` if there are lifetime/type arguments.
1225+ // Only draw `<...>` if there are arguments.
12361226 if len > 0 {
12371227 values. 0 . push_normal ( ">" ) ;
12381228 values. 1 . push_normal ( ">" ) ;
@@ -1244,35 +1234,29 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
12441234 // Foo<Bar<Qux>
12451235 // ------- this type argument is exactly the same as the other type
12461236 // 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+ ) {
12581245 return values;
12591246 }
12601247 // Check for case:
12611248 // let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
12621249 // Bar<Qux>
12631250 // Foo<Bar<Qux>>
12641251 // ------- 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+ ) {
12761260 return values;
12771261 }
12781262
@@ -1343,8 +1327,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
13431327 let mut values = ( DiagStyledString :: normal ( "(" ) , DiagStyledString :: normal ( "(" ) ) ;
13441328 let len = args1. len ( ) ;
13451329 for ( i, ( left, right) ) in args1. iter ( ) . zip ( args2) . enumerate ( ) {
1330+ self . push_comma ( & mut values. 0 , & mut values. 1 , i) ;
13461331 recurse ( left, right, & mut values) ;
1347- self . push_comma ( & mut values. 0 , & mut values. 1 , len, i) ;
13481332 }
13491333 if len == 1 {
13501334 // Keep the output for single element tuples as `(ty,)`.
0 commit comments