From 5880ce396832fd94efb1fc90f2682f209712ba24 Mon Sep 17 00:00:00 2001
From: ben <benlewisj@gmail.com>
Date: Sun, 6 Oct 2019 19:56:05 +1300
Subject: [PATCH 1/2] Fix const arguments not displaying in types mismatch
 diagnostic.

---
 src/librustc/infer/error_reporting/mod.rs     | 19 ++++++++++++++++++-
 .../slice-const-param-mismatch.stderr         | 12 ++++++------
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index d31b527a55b69..f1192c7ce10a9 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -935,6 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         .filter(|(a, b)| a == b)
                         .count();
                     let len = sub1.len() - common_default_params;
+                    let consts_offset = len - sub1.consts().count();
 
                     // Only draw `<...>` if there're lifetime/type arguments.
                     if len > 0 {
@@ -981,7 +982,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     //         ^ elided type as this type argument was the same in both sides
                     let type_arguments = sub1.types().zip(sub2.types());
                     let regions_len = sub1.regions().count();
-                    for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() {
+                    let num_display_types = consts_offset - regions_len;
+                    for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
                         let i = i + regions_len;
                         if ta1 == ta2 {
                             values.0.push_normal("_");
@@ -994,6 +996,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         self.push_comma(&mut values.0, &mut values.1, len, i);
                     }
 
+                    // Do the same for const arguments, if they are equal, do not highlight and
+                    // elide them from the output.
+                    let const_arguments = sub1.consts().zip(sub2.consts());
+                    for (i, (ca1, ca2)) in const_arguments.enumerate() {
+                        let i = i + consts_offset;
+                        if ca1 == ca2 {
+                            values.0.push_normal("_");
+                            values.1.push_normal("_");
+                        } else {
+                            values.0.push_highlighted(ca1.to_string());
+                            values.1.push_highlighted(ca2.to_string());
+                        }
+                        self.push_comma(&mut values.0, &mut values.1, len, i);
+                    }
+
                     // Close the type argument bracket.
                     // Only draw `<...>` if there're lifetime/type arguments.
                     if len > 0 {
diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.stderr
index 72369ab24ebfc..380a70d664e05 100644
--- a/src/test/ui/const-generics/slice-const-param-mismatch.stderr
+++ b/src/test/ui/const-generics/slice-const-param-mismatch.stderr
@@ -12,8 +12,8 @@ error[E0308]: mismatched types
 LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
    |                                   ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
    |
-   = note: expected type `ConstString<>`
-              found type `ConstString<>`
+   = note: expected type `ConstString<"Hello">`
+              found type `ConstString<"World">`
 
 error[E0308]: mismatched types
   --> $DIR/slice-const-param-mismatch.rs:11:33
@@ -21,8 +21,8 @@ error[E0308]: mismatched types
 LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
    |                                  ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
    |
-   = note: expected type `ConstString<>`
-              found type `ConstString<>`
+   = note: expected type `ConstString<"ℇ㇈↦">`
+              found type `ConstString<"ℇ㇈↥">`
 
 error[E0308]: mismatched types
   --> $DIR/slice-const-param-mismatch.rs:13:33
@@ -30,8 +30,8 @@ error[E0308]: mismatched types
 LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
    |                                 ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
    |
-   = note: expected type `ConstBytes<>`
-              found type `ConstBytes<>`
+   = note: expected type `ConstBytes<b"AAA">`
+              found type `ConstBytes<b"BBB">`
 
 error: aborting due to 3 previous errors
 

From 74eac929c270e896752fb826a3fed34aa0ef5725 Mon Sep 17 00:00:00 2001
From: ben <benlewisj@gmail.com>
Date: Mon, 7 Oct 2019 20:39:08 +1300
Subject: [PATCH 2/2] Test diagnostic output of type mismatches for types that
 have const generics arguments.

---
 .../types-mismatch-const-args.rs              | 19 ++++++++++++
 .../types-mismatch-const-args.stderr          | 29 +++++++++++++++++++
 2 files changed, 48 insertions(+)
 create mode 100644 src/test/ui/const-generics/types-mismatch-const-args.rs
 create mode 100644 src/test/ui/const-generics/types-mismatch-const-args.stderr

diff --git a/src/test/ui/const-generics/types-mismatch-const-args.rs b/src/test/ui/const-generics/types-mismatch-const-args.rs
new file mode 100644
index 0000000000000..b25b7331017e7
--- /dev/null
+++ b/src/test/ui/const-generics/types-mismatch-const-args.rs
@@ -0,0 +1,19 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+// tests the diagnostic output of type mismatches for types that have const generics arguments.
+
+use std::marker::PhantomData;
+
+struct A<'a, T, const X: u32, const Y: u32> {
+    data: PhantomData<&'a T>
+}
+
+fn a<'a, 'b>() {
+    let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData };
+    //~^ ERROR mismatched types
+    let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
+    //~^ ERROR mismatched types
+}
+
+pub fn main() {}
diff --git a/src/test/ui/const-generics/types-mismatch-const-args.stderr b/src/test/ui/const-generics/types-mismatch-const-args.stderr
new file mode 100644
index 0000000000000..805a3067d3b6b
--- /dev/null
+++ b/src/test/ui/const-generics/types-mismatch-const-args.stderr
@@ -0,0 +1,29 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/types-mismatch-const-args.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/types-mismatch-const-args.rs:13:41
+   |
+LL |     let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData };
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2u32`, found `4u32`
+   |
+   = note: expected type `A<'_, _, 2u32, _>`
+              found type `A<'_, _, 4u32, _>`
+
+error[E0308]: mismatched types
+  --> $DIR/types-mismatch-const-args.rs:15:41
+   |
+LL |     let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u16, found u32
+   |
+   = note: expected type `A<'a, u16, _, _>`
+              found type `A<'b, u32, _, _>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.