From dd57275c3e4d52b443090d0d75a9a3443bc5ce5c Mon Sep 17 00:00:00 2001
From: Bastian Kauschke <bastian_kauschke@hotmail.de>
Date: Mon, 14 Sep 2020 09:45:02 +0200
Subject: [PATCH 1/2] shrink const infer error

---
 .../infer/error_reporting/need_type_info.rs   | 15 ++++++++-----
 .../cannot-infer-const-args.full.stderr       |  0
 .../cannot-infer-const-args.min.stderr        |  0
 .../{ => infer}/cannot-infer-const-args.rs    |  0
 .../infer/method-chain.full.stderr            | 11 ++++++++++
 .../infer/method-chain.min.stderr             | 11 ++++++++++
 .../ui/const-generics/infer/method-chain.rs   | 22 +++++++++++++++++++
 .../{ => infer}/uninferred-consts.full.stderr |  4 ++--
 .../{ => infer}/uninferred-consts.min.stderr  |  4 ++--
 .../{ => infer}/uninferred-consts.rs          |  0
 10 files changed, 57 insertions(+), 10 deletions(-)
 rename src/test/ui/const-generics/{ => infer}/cannot-infer-const-args.full.stderr (100%)
 rename src/test/ui/const-generics/{ => infer}/cannot-infer-const-args.min.stderr (100%)
 rename src/test/ui/const-generics/{ => infer}/cannot-infer-const-args.rs (100%)
 create mode 100644 src/test/ui/const-generics/infer/method-chain.full.stderr
 create mode 100644 src/test/ui/const-generics/infer/method-chain.min.stderr
 create mode 100644 src/test/ui/const-generics/infer/method-chain.rs
 rename src/test/ui/const-generics/{ => infer}/uninferred-consts.full.stderr (80%)
 rename src/test/ui/const-generics/{ => infer}/uninferred-consts.min.stderr (80%)
 rename src/test/ui/const-generics/{ => infer}/uninferred-consts.rs (100%)

diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 4de84e5ba399c..9be234a7bb8bd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -8,7 +8,7 @@ use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, DefIdTree, Ty};
+use rustc_middle::ty::{self, DefIdTree, InferConst, Ty};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -569,12 +569,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             local_visitor.visit_expr(expr);
         }
 
+        let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
+            self.inner.borrow_mut().const_unification_table().probe_value(vid).origin.span
+        } else {
+            local_visitor.target_span
+        };
+
         let error_code = error_code.into();
-        let mut err = self.tcx.sess.struct_span_err_with_code(
-            local_visitor.target_span,
-            "type annotations needed",
-            error_code,
-        );
+        let mut err =
+            self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code);
 
         err.note("unable to infer the value of a const parameter");
 
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
similarity index 100%
rename from src/test/ui/const-generics/cannot-infer-const-args.full.stderr
rename to src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
similarity index 100%
rename from src/test/ui/const-generics/cannot-infer-const-args.min.stderr
rename to src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.rs b/src/test/ui/const-generics/infer/cannot-infer-const-args.rs
similarity index 100%
rename from src/test/ui/const-generics/cannot-infer-const-args.rs
rename to src/test/ui/const-generics/infer/cannot-infer-const-args.rs
diff --git a/src/test/ui/const-generics/infer/method-chain.full.stderr b/src/test/ui/const-generics/infer/method-chain.full.stderr
new file mode 100644
index 0000000000000..06e4c2e7bc6bc
--- /dev/null
+++ b/src/test/ui/const-generics/infer/method-chain.full.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-chain.rs:21:33
+   |
+LL |     Foo.bar().bar().bar().bar().baz();
+   |                                 ^^^
+   |
+   = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/method-chain.min.stderr b/src/test/ui/const-generics/infer/method-chain.min.stderr
new file mode 100644
index 0000000000000..06e4c2e7bc6bc
--- /dev/null
+++ b/src/test/ui/const-generics/infer/method-chain.min.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-chain.rs:21:33
+   |
+LL |     Foo.bar().bar().bar().bar().baz();
+   |                                 ^^^
+   |
+   = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/method-chain.rs b/src/test/ui/const-generics/infer/method-chain.rs
new file mode 100644
index 0000000000000..b3184642f36b4
--- /dev/null
+++ b/src/test/ui/const-generics/infer/method-chain.rs
@@ -0,0 +1,22 @@
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+struct Foo;
+
+impl Foo {
+    fn bar(self) -> Foo {
+        Foo
+    }
+
+    fn baz<const N: usize>(self) -> Foo {
+        println!("baz: {}", N);
+        Foo
+    }
+}
+
+fn main() {
+    Foo.bar().bar().bar().bar().baz(); //~ ERROR type annotations needed
+}
\ No newline at end of file
diff --git a/src/test/ui/const-generics/uninferred-consts.full.stderr b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
similarity index 80%
rename from src/test/ui/const-generics/uninferred-consts.full.stderr
rename to src/test/ui/const-generics/infer/uninferred-consts.full.stderr
index 2c5af9e65f827..6af49ba64523b 100644
--- a/src/test/ui/const-generics/uninferred-consts.full.stderr
+++ b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
@@ -1,8 +1,8 @@
 error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:14:5
+  --> $DIR/uninferred-consts.rs:14:9
    |
 LL |     Foo.foo();
-   |     ^^^^^^^^^
+   |         ^^^
    |
    = note: unable to infer the value of a const parameter
 
diff --git a/src/test/ui/const-generics/uninferred-consts.min.stderr b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
similarity index 80%
rename from src/test/ui/const-generics/uninferred-consts.min.stderr
rename to src/test/ui/const-generics/infer/uninferred-consts.min.stderr
index 2c5af9e65f827..6af49ba64523b 100644
--- a/src/test/ui/const-generics/uninferred-consts.min.stderr
+++ b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
@@ -1,8 +1,8 @@
 error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:14:5
+  --> $DIR/uninferred-consts.rs:14:9
    |
 LL |     Foo.foo();
-   |     ^^^^^^^^^
+   |         ^^^
    |
    = note: unable to infer the value of a const parameter
 
diff --git a/src/test/ui/const-generics/uninferred-consts.rs b/src/test/ui/const-generics/infer/uninferred-consts.rs
similarity index 100%
rename from src/test/ui/const-generics/uninferred-consts.rs
rename to src/test/ui/const-generics/infer/uninferred-consts.rs

From 035f8791668406bc49fc315253835cbdec247549 Mon Sep 17 00:00:00 2001
From: Bastian Kauschke <bastian_kauschke@hotmail.de>
Date: Mon, 14 Sep 2020 10:08:32 +0200
Subject: [PATCH 2/2] improve const infer err

---
 .../src/infer/error_reporting/need_type_info.rs    | 14 ++++++++++++--
 compiler/rustc_middle/src/infer/unify_key.rs       |  1 +
 .../infer/cannot-infer-const-args.full.stderr      |  2 +-
 .../infer/cannot-infer-const-args.min.stderr       |  2 +-
 .../const-generics/infer/method-chain.full.stderr  |  2 +-
 .../const-generics/infer/method-chain.min.stderr   |  2 +-
 src/test/ui/const-generics/infer/method-chain.rs   |  2 +-
 .../infer/uninferred-consts.full.stderr            |  2 +-
 .../infer/uninferred-consts.min.stderr             |  2 +-
 9 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 9be234a7bb8bd..f87406c2ce469 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -6,6 +6,7 @@ use rustc_hir::def::{DefKind, Namespace};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
 use rustc_middle::hir::map::Map;
+use rustc_middle::infer::unify_key::ConstVariableOriginKind;
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, DefIdTree, InferConst, Ty};
@@ -569,8 +570,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             local_visitor.visit_expr(expr);
         }
 
+        let mut param_name = None;
         let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
-            self.inner.borrow_mut().const_unification_table().probe_value(vid).origin.span
+            let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
+            if let ConstVariableOriginKind::ConstParameterDefinition(param) = origin.kind {
+                param_name = Some(param);
+            }
+            origin.span
         } else {
             local_visitor.target_span
         };
@@ -579,7 +585,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let mut err =
             self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code);
 
-        err.note("unable to infer the value of a const parameter");
+        if let Some(param_name) = param_name {
+            err.note(&format!("cannot infer the value of the const parameter `{}`", param_name));
+        } else {
+            err.note("unable to infer the value of a const parameter");
+        }
 
         err
     }
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 2580ac6bebd86..a60a17befeffd 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -124,6 +124,7 @@ pub struct ConstVariableOrigin {
 pub enum ConstVariableOriginKind {
     MiscVariable,
     ConstInference,
+    // FIXME(const_generics): Consider storing the `DefId` of the param here.
     ConstParameterDefinition(Symbol),
     SubstitutionPlaceholder,
 }
diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
index 053139787edf9..84e75cc376416 100644
--- a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
+++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     foo();
    |     ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `X`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
index 053139787edf9..84e75cc376416 100644
--- a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
+++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     foo();
    |     ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `X`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/infer/method-chain.full.stderr b/src/test/ui/const-generics/infer/method-chain.full.stderr
index 06e4c2e7bc6bc..e65bc3f109681 100644
--- a/src/test/ui/const-generics/infer/method-chain.full.stderr
+++ b/src/test/ui/const-generics/infer/method-chain.full.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     Foo.bar().bar().bar().bar().baz();
    |                                 ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `N`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/infer/method-chain.min.stderr b/src/test/ui/const-generics/infer/method-chain.min.stderr
index 06e4c2e7bc6bc..e65bc3f109681 100644
--- a/src/test/ui/const-generics/infer/method-chain.min.stderr
+++ b/src/test/ui/const-generics/infer/method-chain.min.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     Foo.bar().bar().bar().bar().baz();
    |                                 ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `N`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/infer/method-chain.rs b/src/test/ui/const-generics/infer/method-chain.rs
index b3184642f36b4..9389ca20d106f 100644
--- a/src/test/ui/const-generics/infer/method-chain.rs
+++ b/src/test/ui/const-generics/infer/method-chain.rs
@@ -19,4 +19,4 @@ impl Foo {
 
 fn main() {
     Foo.bar().bar().bar().bar().baz(); //~ ERROR type annotations needed
-}
\ No newline at end of file
+}
diff --git a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
index 6af49ba64523b..e47b6bd5dc691 100644
--- a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
+++ b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     Foo.foo();
    |         ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `N`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
index 6af49ba64523b..e47b6bd5dc691 100644
--- a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
+++ b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     Foo.foo();
    |         ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `N`
 
 error: aborting due to previous error