From 638d1d34ff89803b8558713fa6d5dff79019c854 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Mon, 6 May 2019 13:54:59 +0100
Subject: [PATCH 1/8] Remove duplicate comment

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/libsyntax/parse/parser.rs | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index d46feeab33599..084091f4c2a39 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6045,10 +6045,6 @@ impl<'a> Parser<'a> {
                 });
                 assoc_ty_bindings.push(span);
             } else if self.check_const_arg() {
-                // FIXME(const_generics): to distinguish between idents for types and consts,
-                // we should introduce a GenericArg::Ident in the AST and distinguish when
-                // lowering to the HIR. For now, idents for const args are not permitted.
-
                 // Parse const argument.
                 let expr = if let token::OpenDelim(token::Brace) = self.token {
                     self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?

From 59ebd1b7c2b9558ab31c57878666f0707f33b689 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Mon, 6 May 2019 13:55:14 +0100
Subject: [PATCH 2/8] Shift const vars through binders

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc/ty/subst.rs | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 8d51fbc174a04..e5bd3f15efe95 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -618,8 +618,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
             }
         };
 
-        // FIXME(const_generics): shift const through binders
-        ct
+        self.shift_vars_through_binders(ct)
     }
 
     /// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs
@@ -664,15 +663,15 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
     /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the
     /// first case we do not increase the De Bruijn index and in the second case we do. The reason
     /// is that only in the second case have we passed through a fn binder.
-    fn shift_vars_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        debug!("shift_vars(ty={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})",
-               ty, self.binders_passed, ty.has_escaping_bound_vars());
+    fn shift_vars_through_binders<T: TypeFoldable<'tcx>>(&self, val: T) -> T {
+        debug!("shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})",
+               val, self.binders_passed, val.has_escaping_bound_vars());
 
-        if self.binders_passed == 0 || !ty.has_escaping_bound_vars() {
-            return ty;
+        if self.binders_passed == 0 || !val.has_escaping_bound_vars() {
+            return val;
         }
 
-        let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed);
+        let result = ty::fold::shift_vars(self.tcx(), &val, self.binders_passed);
         debug!("shift_vars: shifted result = {:?}", result);
 
         result

From ad78fcf5246c9accb2a35ced91d85b710648abc9 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Mon, 6 May 2019 13:55:28 +0100
Subject: [PATCH 3/8] Ignore const parameters when constructing type bounds in
 rustdoc

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustdoc/clean/mod.rs | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index de74a6a540055..3a260db806520 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1706,9 +1706,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
                 }
                 Some(param.clean(cx))
             }
-            ty::GenericParamDefKind::Const { .. } => {
-                unimplemented!() // FIXME(const_generics)
-            }
+            ty::GenericParamDefKind::Const { .. } => None,
         }).collect::<Vec<GenericParamDef>>();
 
         let mut where_predicates = preds.predicates.iter()

From c6197541f73c570f5104c36920b387992c7658d2 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Mon, 6 May 2019 14:05:26 +0100
Subject: [PATCH 4/8] Implement TypeFoldable for InferConst

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc/ty/structural_impls.rs | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index bab9527dd07f6..f81394a878f5a 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -6,7 +6,7 @@
 use crate::hir::def::Namespace;
 use crate::mir::ProjectionKind;
 use crate::mir::interpret::ConstValue;
-use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid};
+use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::print::{FmtPrinter, Printer};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -1352,8 +1352,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         match *self {
             ConstValue::ByRef(ptr, alloc) => ConstValue::ByRef(ptr, alloc),
-            // FIXME(const_generics): implement TypeFoldable for InferConst
-            ConstValue::Infer(ic) => ConstValue::Infer(ic),
+            ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)),
             ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
             ConstValue::Placeholder(p) => ConstValue::Placeholder(p),
             ConstValue::Scalar(a) => ConstValue::Scalar(a),
@@ -1366,8 +1365,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match *self {
             ConstValue::ByRef(..) => false,
-            // FIXME(const_generics): implement TypeFoldable for InferConst
-            ConstValue::Infer(_) => false,
+            ConstValue::Infer(ic) => ic.visit_with(visitor),
             ConstValue::Param(p) => p.visit_with(visitor),
             ConstValue::Placeholder(_) => false,
             ConstValue::Scalar(_) => false,
@@ -1376,3 +1374,13 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
         }
     }
 }
+
+impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
+        *self
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
+        false
+    }
+}

From 670cf11de22583e1192636f0e6c36007ebcbb776 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Mon, 6 May 2019 14:16:07 +0100
Subject: [PATCH 5/8] Clean up `push_const_name`

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc_mir/monomorphize/item.rs | 40 +++++++++++++++++----------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index b001a09529e5b..999e7402afd93 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -3,7 +3,7 @@ use rustc::hir;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::interpret::ConstValue;
 use rustc::session::config::OptLevel;
-use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, ParamConst};
+use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts};
 use rustc::ty::subst::{SubstsRef, InternalSubsts};
 use syntax::ast;
 use syntax::attr::InlineAttr;
@@ -240,11 +240,11 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
     }
 
     // Pushes the type name of the specified type to the provided string.
-    // If 'debug' is true, printing normally unprintable types is allowed
-    // (e.g. ty::GeneratorWitness). This parameter should only be set when
-    // this method is being used for logging purposes (e.g. with debug! or info!)
-    // When being used for codegen purposes, 'debug' should be set to 'false'
-    // in order to catch unexpected types that should never end up in a type name
+    // If `debug` is true, printing normally unprintable types is allowed
+    // (e.g. `ty::GeneratorWitness`). This parameter should only be set when
+    // this method is being used for logging purposes (e.g. with `debug!` or `info!`)
+    // When being used for codegen purposes, `debug` should be set to `false`
+    // in order to catch unexpected types that should never end up in a type name.
     pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
         match t.sty {
             ty::Bool              => output.push_str("bool"),
@@ -387,22 +387,34 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
                 if debug {
                     output.push_str(&format!("`{:?}`", t));
                 } else {
-                    bug!("DefPathBasedNames: Trying to create type name for \
-                                         unexpected type: {:?}", t);
+                    bug!(
+                        "DefPathBasedNames: trying to create type name for unexpected type: {:?}",
+                        t,
+                    );
                 }
             }
         }
     }
 
-    // FIXME(const_generics): handle debug printing.
+    // Pushes the the name of the specified const to the provided string.
+    // If `debug` is true, usually-unprintable consts (such as `Infer`) will be printed,
+    // as well as the unprintable types of constants (see `push_type_name` for more details).
     pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
         match c.val {
-            ConstValue::Infer(..) | ConstValue::Placeholder(_) => output.push_str("_"),
-            ConstValue::Param(ParamConst { name, .. }) => {
-                write!(output, "{}", name).unwrap();
+            ConstValue::Scalar(..) | ConstValue::Slice(..) | ConstValue::ByRef(..) => {
+                // FIXME(const_generics): we could probably do a better job here.
+                write!(output, "{:?}", c).unwrap()
+            }
+            _ => {
+                if debug {
+                    write!(output, "{:?}", c).unwrap()
+                } else {
+                    bug!(
+                        "DefPathBasedNames: trying to create const name for unexpected const: {:?}",
+                        c,
+                    );
+                }
             }
-            ConstValue::Unevaluated(..) => output.push_str("_: _"),
-            _ => write!(output, "{:?}", c).unwrap(),
         }
         output.push_str(": ");
         self.push_type_name(c.ty, output, debug);

From c0454f0638f235dd7c8b4bb57ea5614e5e877746 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Mon, 6 May 2019 14:16:28 +0100
Subject: [PATCH 6/8] Remove incorrect FIXME

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc_typeck/check/mod.rs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index e404a8e6972c8..82fcf8ff52f83 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -5785,8 +5785,6 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty
     );
 
-    // FIXME(const_generics): we probably want to check the bounds for const parameters too.
-
     if own_counts.types == 0 {
         return;
     }

From 5fc0395053c732c8becf0e1dca7000554c352ccd Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Mon, 6 May 2019 14:17:48 +0100
Subject: [PATCH 7/8] Resolve a couple of `unimplemented!()`s

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
---
 src/librustc/infer/canonical/query_response.rs | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 8225ed70c5827..413c1428ff954 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -318,8 +318,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
                     obligations.extend(ok.into_obligations());
                 }
 
-                (UnpackedKind::Const(..), UnpackedKind::Const(..)) => {
-                    unimplemented!() // FIXME(const_generics)
+                (UnpackedKind::Const(v1), UnpackedKind::Const(v2)) => {
+                    let ok = self.at(cause, param_env).eq(v1, v2)?;
+                    obligations.extend(ok.into_obligations());
                 }
 
                 _ => {
@@ -626,8 +627,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
                         obligations
                             .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations());
                     }
-                    (UnpackedKind::Const(..), UnpackedKind::Const(..)) => {
-                        unimplemented!() // FIXME(const_generics)
+                    (UnpackedKind::Const(v1), UnpackedKind::Const(v2)) => {
+                        let ok = self.at(cause, param_env).eq(v1, v2)?;
+                        obligations.extend(ok.into_obligations());
                     }
                     _ => {
                         bug!("kind mismatch, cannot unify {:?} and {:?}", value1, value2,);

From 9a2772aff0e6c2058fb52a844b4593eabd18fcbc Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Mon, 6 May 2019 15:07:46 +0100
Subject: [PATCH 8/8] Implement `ToTrace` for `ty::Const`

---
 src/librustc/infer/at.rs                  | 15 +++++++++++++++
 src/librustc/infer/error_reporting/mod.rs |  1 +
 src/librustc/infer/mod.rs                 |  2 ++
 3 files changed, 18 insertions(+)

diff --git a/src/librustc/infer/at.rs b/src/librustc/infer/at.rs
index 34cd3ae5427e0..5772110889290 100644
--- a/src/librustc/infer/at.rs
+++ b/src/librustc/infer/at.rs
@@ -27,6 +27,7 @@
 
 use super::*;
 
+use crate::ty::Const;
 use crate::ty::relate::{Relate, TypeRelation};
 
 pub struct At<'a, 'gcx: 'tcx, 'tcx: 'a> {
@@ -308,6 +309,20 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
     }
 }
 
+impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> {
+    fn to_trace(cause: &ObligationCause<'tcx>,
+                a_is_expected: bool,
+                a: Self,
+                b: Self)
+                -> TypeTrace<'tcx>
+    {
+        TypeTrace {
+            cause: cause.clone(),
+            values: Consts(ExpectedFound::new(a_is_expected, a, b))
+        }
+    }
+}
+
 impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
     fn to_trace(cause: &ObligationCause<'tcx>,
                 a_is_expected: bool,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 95b566d4a1b69..4b6e7da333081 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -1260,6 +1260,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         match *values {
             infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
             infer::Regions(ref exp_found) => self.expected_found_str(exp_found),
+            infer::Consts(ref exp_found) => self.expected_found_str(exp_found),
             infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
             infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
         }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 5846e604cfc09..b5a9184079aa6 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -232,6 +232,7 @@ pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
 pub enum ValuePairs<'tcx> {
     Types(ExpectedFound<Ty<'tcx>>),
     Regions(ExpectedFound<ty::Region<'tcx>>),
+    Consts(ExpectedFound<&'tcx ty::Const<'tcx>>),
     TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
     PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
 }
@@ -1730,6 +1731,7 @@ EnumTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
         (ValuePairs::Types)(a),
         (ValuePairs::Regions)(a),
+        (ValuePairs::Consts)(a),
         (ValuePairs::TraitRefs)(a),
         (ValuePairs::PolyTraitRefs)(a),
     }