From 9220558c246d6d1610e7a9b20bd031559b868236 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 22 Oct 2019 14:00:19 +0100
Subject: [PATCH 1/5] Fix an issue with const inference variables sticking
 around under Chalk + NLL

---
 src/librustc/infer/combine.rs        | 14 ++++------
 src/librustc/infer/nll_relate/mod.rs | 41 ++++++++++++++++------------
 2 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index f06dbc72cd9..2e724ac56ee 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -602,19 +602,15 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
         assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
 
-        match c {
-            ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => {
+        match c.val {
+            ConstValue::Infer(InferConst::Var(vid)) => {
                 let mut variable_table = self.infcx.const_unification_table.borrow_mut();
-                match variable_table.probe_value(*vid).val.known() {
-                    Some(u) => {
-                        self.relate(&u, &u)
-                    }
+                match variable_table.probe_value(vid).val.known() {
+                    Some(u) => self.relate(&u, &u),
                     None => Ok(c),
                 }
             }
-            _ => {
-                relate::super_relate_consts(self, c, c)
-            }
+            _ => relate::super_relate_consts(self, c, c),
         }
     }
 }
diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs
index 64ef0421808..8d59f455cbb 100644
--- a/src/librustc/infer/nll_relate/mod.rs
+++ b/src/librustc/infer/nll_relate/mod.rs
@@ -27,7 +27,7 @@ use crate::ty::error::TypeError;
 use crate::ty::fold::{TypeFoldable, TypeVisitor};
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use crate::ty::subst::GenericArg;
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt, InferConst};
 use crate::mir::interpret::ConstValue;
 use rustc_data_structures::fx::FxHashMap;
 use std::fmt::Debug;
@@ -616,15 +616,20 @@ where
     fn consts(
         &mut self,
         a: &'tcx ty::Const<'tcx>,
-        b: &'tcx ty::Const<'tcx>,
+        mut b: &'tcx ty::Const<'tcx>,
     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
-        if let ty::Const { val: ConstValue::Bound(..), .. } = a {
-            // FIXME(const_generics): I'm unsure how this branch should actually be handled,
-            // so this is probably not correct.
-            self.infcx.super_combine_consts(self, a, b)
-        } else {
-            debug!("consts(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance);
-            relate::super_relate_consts(self, a, b)
+        let a = self.infcx.shallow_resolve(a);
+
+        if !D::forbid_inference_vars() {
+            b = self.infcx.shallow_resolve(b);
+        }
+
+        match b.val {
+            ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
+                // Forbid inference variables in the RHS.
+                bug!("unexpected inference var {:?}", b)
+            }
+            _ => self.infcx.super_combine_consts(self, a, b)
         }
     }
 
@@ -991,15 +996,15 @@ where
         a: &'tcx ty::Const<'tcx>,
         _: &'tcx ty::Const<'tcx>,
     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
-        debug!("TypeGeneralizer::consts(a={:?})", a);
-
-        if let ty::Const { val: ConstValue::Bound(..), .. } = a {
-            bug!(
-                "unexpected inference variable encountered in NLL generalization: {:?}",
-                a
-            );
-        } else {
-            relate::super_relate_consts(self, a, a)
+        match a.val {
+            ConstValue::Infer(InferConst::Var(vid)) => {
+                let mut variable_table = self.infcx.const_unification_table.borrow_mut();
+                match variable_table.probe_value(vid).val.known() {
+                    Some(u) => self.relate(&u, &u),
+                    None => Ok(a),
+                }
+            }
+            _ => relate::super_relate_consts(self, a, a),
         }
     }
 

From 51c687446d65fe271972f6371639334bb10da6db Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 22 Oct 2019 14:07:20 +0100
Subject: [PATCH 2/5] Add regression test for #65675

---
 src/test/ui/const-generics/issues/issue-65675.rs     | 10 ++++++++++
 src/test/ui/const-generics/issues/issue-65675.stderr |  8 ++++++++
 2 files changed, 18 insertions(+)
 create mode 100644 src/test/ui/const-generics/issues/issue-65675.rs
 create mode 100644 src/test/ui/const-generics/issues/issue-65675.stderr

diff --git a/src/test/ui/const-generics/issues/issue-65675.rs b/src/test/ui/const-generics/issues/issue-65675.rs
new file mode 100644
index 00000000000..3ca527313f9
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-65675.rs
@@ -0,0 +1,10 @@
+// run-pass
+// compile-flags: -Z chalk
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+pub struct Foo<T, const N: usize>([T; N]);
+impl<T, const N: usize> Foo<T, {N}> {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-65675.stderr b/src/test/ui/const-generics/issues/issue-65675.stderr
new file mode 100644
index 00000000000..60b388e6278
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-65675.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-65675.rs:4:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+

From cc7294c751fd700b77c3556eaae8507661f08f22 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Wed, 23 Oct 2019 17:09:56 +0100
Subject: [PATCH 3/5] Add regression test for #62579

---
 .../const-generics/issues/issue-62579-no-match.rs | 15 +++++++++++++++
 .../issues/issue-62579-no-match.stderr            |  8 ++++++++
 2 files changed, 23 insertions(+)
 create mode 100644 src/test/ui/const-generics/issues/issue-62579-no-match.rs
 create mode 100644 src/test/ui/const-generics/issues/issue-62579-no-match.stderr

diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs
new file mode 100644
index 00000000000..0ff7ddc41fe
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62579-no-match.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+#[derive(PartialEq, Eq)]
+struct NoMatch;
+
+fn foo<const T: NoMatch>() -> bool {
+    true
+}
+
+fn main() {
+    foo::<{NoMatch}>();
+}
diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr
new file mode 100644
index 00000000000..759d5fdeb4c
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-62579-no-match.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+

From 12f68e6987c4669b90a6cdac1643b99b6c677aea Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Wed, 23 Oct 2019 17:40:18 +0100
Subject: [PATCH 4/5] Account for const generalisation in combine

---
 src/librustc/infer/combine.rs | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index 2e724ac56ee..a6c3c2de139 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -605,9 +605,21 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
         match c.val {
             ConstValue::Infer(InferConst::Var(vid)) => {
                 let mut variable_table = self.infcx.const_unification_table.borrow_mut();
-                match variable_table.probe_value(vid).val.known() {
-                    Some(u) => self.relate(&u, &u),
-                    None => Ok(c),
+                let var_value = variable_table.probe_value(vid);
+                match var_value.val {
+                    ConstVariableValue::Known { value: u } => self.relate(&u, &u),
+                    ConstVariableValue::Unknown { universe } => {
+                        if self.for_universe.can_name(universe) {
+                            Ok(c)
+                        } else {
+                            let new_var_id = variable_table.new_key(ConstVarValue {
+                                origin: var_value.origin,
+                                val: ConstVariableValue::Unknown { universe: self.for_universe },
+                            });
+                            let u = self.tcx().mk_const_var(new_var_id, c.ty);
+                            return Ok(u);
+                        }
+                    }
                 }
             }
             _ => relate::super_relate_consts(self, c, c),

From 624e34a5d02d47b807bad3a81aa7ce0c088d2452 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Wed, 23 Oct 2019 18:00:35 +0100
Subject: [PATCH 5/5] Account for const generalisation in nll_relate

---
 src/librustc/infer/combine.rs        |  7 +++----
 src/librustc/infer/nll_relate/mod.rs | 21 ++++++++++++++++++---
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index a6c3c2de139..51ae4e49493 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -494,7 +494,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 if sub_vid == self.for_vid_sub_root {
                     // If sub-roots are equal, then `for_vid` and
                     // `vid` are related via subtyping.
-                    return Err(TypeError::CyclicTy(self.root_ty));
+                    Err(TypeError::CyclicTy(self.root_ty))
                 } else {
                     match variables.probe(vid) {
                         TypeVariableValue::Known { value: u } => {
@@ -527,7 +527,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                             let u = self.tcx().mk_ty_var(new_var_id);
                             debug!("generalize: replacing original vid={:?} with new={:?}",
                                    vid, u);
-                            return Ok(u);
+                            Ok(u)
                         }
                     }
                 }
@@ -616,8 +616,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                                 origin: var_value.origin,
                                 val: ConstVariableValue::Unknown { universe: self.for_universe },
                             });
-                            let u = self.tcx().mk_const_var(new_var_id, c.ty);
-                            return Ok(u);
+                            Ok(self.tcx().mk_const_var(new_var_id, c.ty))
                         }
                     }
                 }
diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs
index 8d59f455cbb..d6f76e9ee34 100644
--- a/src/librustc/infer/nll_relate/mod.rs
+++ b/src/librustc/infer/nll_relate/mod.rs
@@ -28,6 +28,7 @@ use crate::ty::fold::{TypeFoldable, TypeVisitor};
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use crate::ty::subst::GenericArg;
 use crate::ty::{self, Ty, TyCtxt, InferConst};
+use crate::infer::{ConstVariableValue, ConstVarValue};
 use crate::mir::interpret::ConstValue;
 use rustc_data_structures::fx::FxHashMap;
 use std::fmt::Debug;
@@ -324,7 +325,7 @@ where
         let vid = pair.vid();
         let value_ty = pair.value_ty();
 
-        // FIXME -- this logic assumes invariance, but that is wrong.
+        // FIXME(invariance) -- this logic assumes invariance, but that is wrong.
         // This only presently applies to chalk integration, as NLL
         // doesn't permit type variables to appear on both sides (and
         // doesn't use lazy norm).
@@ -629,6 +630,7 @@ where
                 // Forbid inference variables in the RHS.
                 bug!("unexpected inference var {:?}", b)
             }
+            // FIXME(invariance): see the related FIXME above.
             _ => self.infcx.super_combine_consts(self, a, b)
         }
     }
@@ -997,11 +999,24 @@ where
         _: &'tcx ty::Const<'tcx>,
     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
         match a.val {
+            ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
+                bug!(
+                    "unexpected inference variable encountered in NLL generalization: {:?}",
+                    a
+                );
+            }
             ConstValue::Infer(InferConst::Var(vid)) => {
                 let mut variable_table = self.infcx.const_unification_table.borrow_mut();
-                match variable_table.probe_value(vid).val.known() {
+                let var_value = variable_table.probe_value(vid);
+                match var_value.val.known() {
                     Some(u) => self.relate(&u, &u),
-                    None => Ok(a),
+                    None => {
+                        let new_var_id = variable_table.new_key(ConstVarValue {
+                            origin: var_value.origin,
+                            val: ConstVariableValue::Unknown { universe: self.universe },
+                        });
+                        Ok(self.tcx().mk_const_var(new_var_id, a.ty))
+                    }
                 }
             }
             _ => relate::super_relate_consts(self, a, a),