about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBastian Kauschke <bastian_kauschke@hotmail.de>2020-11-07 12:37:28 +0100
committerBastian Kauschke <bastian_kauschke@hotmail.de>2020-11-07 12:39:52 +0100
commit439171e094e00e7d3ac0b2d8f65c23cac87836f2 (patch)
tree69ba3c86f6f4079ce146ce3d33b9feddfdb691d3
parent0256d065d4901b63def6c04013da4f781d0752bb (diff)
downloadrust-439171e094e00e7d3ac0b2d8f65c23cac87836f2.tar.gz
rust-439171e094e00e7d3ac0b2d8f65c23cac87836f2.zip
look at assoc ct, check the type of nodes
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs17
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs31
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs16
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr14
4 files changed, 78 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 638a8253e7e..e1721a5a88a 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -512,6 +512,13 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
                 block = &self.body.basic_blocks()[next];
             } else {
                 assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap());
+                // `AbstractConst`s should not contain any promoteds as they require references which
+                // are not allowed.
+                assert!(!self.nodes.iter().any(|n| matches!(
+                    n.node,
+                    Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(_, _, Some(_)), ty: _ })
+                )));
+
                 self.nodes[self.locals[mir::RETURN_PLACE]].used = true;
                 if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
                     self.error(Some(unused.span), "dead code")?;
@@ -609,6 +616,10 @@ pub(super) fn try_unify<'tcx>(
         (Node::Leaf(a_ct), Node::Leaf(b_ct)) => {
             let a_ct = a_ct.subst(tcx, a.substs);
             let b_ct = b_ct.subst(tcx, b.substs);
+            if a_ct.ty != b_ct.ty {
+                return false;
+            }
+
             match (a_ct.val, b_ct.val) {
                 // We can just unify errors with everything to reduce the amount of
                 // emitted errors here.
@@ -621,6 +632,12 @@ pub(super) fn try_unify<'tcx>(
                 // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This
                 // means that we only allow inference variables if they are equal.
                 (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val,
+                // We may want to instead recurse into unevaluated constants here. That may require some
+                // care to prevent infinite recursion, so let's just ignore this for now.
+                (
+                    ty::ConstKind::Unevaluated(a_def, a_substs, None),
+                    ty::ConstKind::Unevaluated(b_def, b_substs, None),
+                ) => a_def == b_def && a_substs == b_substs,
                 // FIXME(const_evaluatable_checked): We may want to either actually try
                 // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
                 // this, for now we just return false here.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs b/src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs
new file mode 100644
index 00000000000..533fe55b45b
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs
@@ -0,0 +1,31 @@
+// run-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+pub trait BlockCipher {
+    const BLOCK_SIZE: usize;
+}
+
+struct FooCipher;
+impl BlockCipher for FooCipher {
+    const BLOCK_SIZE: usize = 64;
+}
+
+struct BarCipher;
+impl BlockCipher for BarCipher {
+    const BLOCK_SIZE: usize = 32;
+}
+
+pub struct Block<C>(C);
+
+pub fn test<C: BlockCipher, const M: usize>()
+where
+    [u8; M - C::BLOCK_SIZE]: Sized,
+{
+    let _ = [0; M - C::BLOCK_SIZE];
+}
+
+fn main() {
+    test::<FooCipher, 128>();
+    test::<BarCipher, 64>();
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs
new file mode 100644
index 00000000000..05049d9c2a6
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs
@@ -0,0 +1,16 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+use std::mem::size_of;
+use std::marker::PhantomData;
+
+struct Foo<T>(PhantomData<T>);
+
+fn test<T>() -> [u8; size_of::<T>()] {
+    [0; size_of::<Foo<T>>()]
+    //~^ ERROR unconstrained generic constant
+}
+
+fn main() {
+    test::<u32>();
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr
new file mode 100644
index 00000000000..1f6dddb04e5
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr
@@ -0,0 +1,14 @@
+error: unconstrained generic constant
+  --> $DIR/different-fn.rs:10:9
+   |
+LL |     [0; size_of::<Foo<T>>()]
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+help: consider adding a `where` bound for this expression
+  --> $DIR/different-fn.rs:10:9
+   |
+LL |     [0; size_of::<Foo<T>>()]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+