about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_middle/ty/relate.rs36
-rw-r--r--src/test/ui/const-generics/different_byref.rs11
-rw-r--r--src/test/ui/const-generics/different_byref.stderr20
-rw-r--r--src/test/ui/const-generics/issues/issue-68615-adt.rs11
-rw-r--r--src/test/ui/const-generics/issues/issue-68615-array.rs11
5 files changed, 87 insertions, 2 deletions
diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs
index f4f0b6c41b9..4bfa46367d0 100644
--- a/src/librustc_middle/ty/relate.rs
+++ b/src/librustc_middle/ty/relate.rs
@@ -11,6 +11,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_hir as ast;
 use rustc_hir::def_id::DefId;
+use rustc_span::DUMMY_SP;
 use rustc_target::spec::abi;
 use std::iter;
 use std::rc::Rc;
@@ -507,6 +508,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
     a: &'tcx ty::Const<'tcx>,
     b: &'tcx ty::Const<'tcx>,
 ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
+    debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
     let tcx = relation.tcx();
 
     let eagerly_eval = |x: &'tcx ty::Const<'tcx>| {
@@ -561,7 +563,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
                     }
                 }
 
-                (a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => {
+                (ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
                     let a_bytes = get_slice_bytes(&tcx, a_val);
                     let b_bytes = get_slice_bytes(&tcx, b_val);
                     if a_bytes == b_bytes {
@@ -571,7 +573,37 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
                     }
                 }
 
-                // FIXME(const_generics): handle `ConstValue::ByRef`.
+                (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
+                    match a.ty.kind {
+                        ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
+                            let a_destructured = tcx.destructure_const(relation.param_env().and(a));
+                            let b_destructured = tcx.destructure_const(relation.param_env().and(b));
+
+                            // Both the variant and each field have to be equal.
+                            if a_destructured.variant == b_destructured.variant {
+                                for (a_field, b_field) in
+                                    a_destructured.fields.iter().zip(b_destructured.fields.iter())
+                                {
+                                    relation.consts(a_field, b_field)?;
+                                }
+
+                                Ok(a_val)
+                            } else {
+                                Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+                            }
+                        }
+                        // FIXME(const_generics): There are probably some `TyKind`s
+                        // which should be handled here.
+                        _ => {
+                            tcx.sess.delay_span_bug(
+                                DUMMY_SP,
+                                &format!("unexpected consts: a: {:?}, b: {:?}", a, b),
+                            );
+                            Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+                        }
+                    }
+                }
+
                 _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
             };
 
diff --git a/src/test/ui/const-generics/different_byref.rs b/src/test/ui/const-generics/different_byref.rs
new file mode 100644
index 00000000000..c52a5b8061d
--- /dev/null
+++ b/src/test/ui/const-generics/different_byref.rs
@@ -0,0 +1,11 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Const<const V: [usize; 1]> {}
+
+fn main() {
+    let mut x = Const::<{ [3] }> {};
+    x = Const::<{ [4] }> {};
+    //~^ ERROR mismatched types
+
+}
diff --git a/src/test/ui/const-generics/different_byref.stderr b/src/test/ui/const-generics/different_byref.stderr
new file mode 100644
index 00000000000..9ea2aace89a
--- /dev/null
+++ b/src/test/ui/const-generics/different_byref.stderr
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/different_byref.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/different_byref.rs:8:9
+   |
+LL |     x = Const::<{ [4] }> {};
+   |         ^^^^^^^^^^^^^^^^^^^ expected `3usize`, found `4usize`
+   |
+   = note: expected struct `Const<[3usize]>`
+              found struct `Const<[4usize]>`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-68615-adt.rs b/src/test/ui/const-generics/issues/issue-68615-adt.rs
new file mode 100644
index 00000000000..140bb28ec5a
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-68615-adt.rs
@@ -0,0 +1,11 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct Const<const V: [usize; 0]> {}
+type MyConst = Const<{ [] }>;
+
+fn main() {
+    let _x = Const::<{ [] }> {};
+    let _y = MyConst {};
+}
diff --git a/src/test/ui/const-generics/issues/issue-68615-array.rs b/src/test/ui/const-generics/issues/issue-68615-array.rs
new file mode 100644
index 00000000000..c384bc1e36d
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-68615-array.rs
@@ -0,0 +1,11 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct Foo<const V: [usize; 0] > {}
+
+type MyFoo = Foo<{ [] }>;
+
+fn main() {
+    let _ = Foo::<{ [] }> {};
+}