From 8b141a24d05c86b4c074715803f0c29783f8f9bc Mon Sep 17 00:00:00 2001
From: Dominik Stolz <d.stolz@tum.de>
Date: Thu, 7 Oct 2021 23:14:33 +0200
Subject: [PATCH 1/3] Add variance constraints for const params

---
 .../rustc_typeck/src/variance/constraints.rs  | 30 +++++++++++++++----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs
index 1c8ac10818c..33c27ce86dd 100644
--- a/compiler/rustc_typeck/src/variance/constraints.rs
+++ b/compiler/rustc_typeck/src/variance/constraints.rs
@@ -223,8 +223,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                     self.add_constraints_from_region(current, lt, variance_i)
                 }
                 GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i),
-                GenericArgKind::Const(_) => {
-                    // Consts impose no constraints.
+                GenericArgKind::Const(val) => {
+                    self.add_constraints_from_const(current, val, variance_i)
                 }
             }
         }
@@ -263,7 +263,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
             }
 
-            ty::Array(typ, _) => {
+            ty::Array(typ, len) => {
+                self.add_constraints_from_const(current, len, variance);
                 self.add_constraints_from_ty(current, typ, variance);
             }
 
@@ -385,13 +386,32 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                     self.add_constraints_from_region(current, lt, variance_i)
                 }
                 GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i),
-                GenericArgKind::Const(_) => {
-                    // Consts impose no constraints.
+                GenericArgKind::Const(val) => {
+                    self.add_constraints_from_const(current, val, variance)
                 }
             }
         }
     }
 
+    /// Adds constraints appropriate for a const expression `val`
+    /// in a context with ambient variance `variance`
+    fn add_constraints_from_const(
+        &mut self,
+        current: &CurrentItem,
+        val: &ty::Const<'tcx>,
+        variance: VarianceTermPtr<'a>,
+    ) {
+        debug!("add_constraints_from_const(val={:?}, variance={:?})", val, variance);
+
+        match &val.val {
+            ty::ConstKind::Unevaluated(uv) => {
+                let substs = uv.substs(self.tcx());
+                self.add_constraints_from_invariant_substs(current, substs, variance);
+            }
+            _ => {}
+        }
+    }
+
     /// Adds constraints appropriate for a function with signature
     /// `sig` appearing in a context with ambient variance `variance`
     fn add_constraints_from_sig(

From 59b36bcfb5fa50b370869f5073a57d514f59e0c8 Mon Sep 17 00:00:00 2001
From: Dominik Stolz <d.stolz@tum.de>
Date: Tue, 12 Oct 2021 21:50:44 +0200
Subject: [PATCH 2/3] Add UI test for the variance of types appearing in consts

---
 .../ui/variance/variance-associated-consts.rs   | 17 +++++++++++++++++
 .../variance/variance-associated-consts.stderr  | 10 ++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 src/test/ui/variance/variance-associated-consts.rs
 create mode 100644 src/test/ui/variance/variance-associated-consts.stderr

diff --git a/src/test/ui/variance/variance-associated-consts.rs b/src/test/ui/variance/variance-associated-consts.rs
new file mode 100644
index 00000000000..da55bc96244
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-consts.rs
@@ -0,0 +1,17 @@
+// Test that the variance computation considers types that
+// appear in const expressions to be invariant.
+
+#![feature(rustc_attrs)]
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+trait Trait {
+    const Const: usize;
+}
+
+#[rustc_variance]
+struct Foo<T: Trait> { //~ ERROR [o]
+    field: [u8; <T as Trait>::Const]
+}
+
+fn main() { }
diff --git a/src/test/ui/variance/variance-associated-consts.stderr b/src/test/ui/variance/variance-associated-consts.stderr
new file mode 100644
index 00000000000..d1bf34781df
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-consts.stderr
@@ -0,0 +1,10 @@
+error[E0208]: [o]
+  --> $DIR/variance-associated-consts.rs:13:1
+   |
+LL | / struct Foo<T: Trait> {
+LL | |     field: [u8; <T as Trait>::Const]
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+

From a400f1058e53cf9603e82b7fd00d42df159b8361 Mon Sep 17 00:00:00 2001
From: Dominik Stolz <d.stolz@tum.de>
Date: Tue, 12 Oct 2021 22:47:34 +0200
Subject: [PATCH 3/3] Bless tests

---
 .../const-generics/issues/issue-67375.full.stderr  | 12 +-----------
 src/test/ui/const-generics/issues/issue-67375.rs   |  2 +-
 .../issues/issue-67945-1.full.stderr               | 14 ++------------
 src/test/ui/const-generics/issues/issue-67945-1.rs |  2 +-
 4 files changed, 5 insertions(+), 25 deletions(-)

diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr
index 0f0e339655b..0cf69879a5c 100644
--- a/src/test/ui/const-generics/issues/issue-67375.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr
@@ -8,15 +8,5 @@ LL |     inner: [(); { [|_: &T| {}; 0].len() }],
    |
    = help: consider moving this anonymous constant into a `const` function
 
-error[E0392]: parameter `T` is never used
-  --> $DIR/issue-67375.rs:5:12
-   |
-LL | struct Bug<T> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
+error: aborting due to previous error
 
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67375.rs b/src/test/ui/const-generics/issues/issue-67375.rs
index b5b842a15ae..8b4b276bae0 100644
--- a/src/test/ui/const-generics/issues/issue-67375.rs
+++ b/src/test/ui/const-generics/issues/issue-67375.rs
@@ -3,7 +3,7 @@
 #![cfg_attr(full, feature(generic_const_exprs))]
 
 struct Bug<T> {
-    //~^ ERROR parameter `T` is never used
+    //[min]~^ ERROR parameter `T` is never used
     inner: [(); { [|_: &T| {}; 0].len() }],
     //[min]~^ ERROR generic parameters may not be used in const operations
     //[full]~^^ ERROR overly complex generic constant
diff --git a/src/test/ui/const-generics/issues/issue-67945-1.full.stderr b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr
index 1edc7828caa..8e18fcdffab 100644
--- a/src/test/ui/const-generics/issues/issue-67945-1.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr
@@ -12,16 +12,6 @@ LL |         let x: S = MaybeUninit::uninit();
    = note: expected type parameter `S`
                        found union `MaybeUninit<_>`
 
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-1.rs:7:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+error: aborting due to previous error
 
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0308, E0392.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-1.rs b/src/test/ui/const-generics/issues/issue-67945-1.rs
index 7b7e8428639..99f88bc8e10 100644
--- a/src/test/ui/const-generics/issues/issue-67945-1.rs
+++ b/src/test/ui/const-generics/issues/issue-67945-1.rs
@@ -5,7 +5,7 @@
 use std::mem::MaybeUninit;
 
 struct Bug<S> {
-    //~^ ERROR parameter `S` is never used
+    //[min]~^ ERROR parameter `S` is never used
     A: [(); {
         let x: S = MaybeUninit::uninit();
         //[min]~^ ERROR generic parameters may not be used in const operations