about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEllen <supbscripter@gmail.com>2021-02-01 20:05:43 +0000
committerEllen <supbscripter@gmail.com>2021-02-01 20:05:50 +0000
commit7f8530f16b8cc908cb77970967addf39ae1a975d (patch)
tree8d1794b58d4356023bdc8419a827cf07210c0bce
parent02b85d722050d61b40ae9746b3bac54ab55b1056 (diff)
downloadrust-7f8530f16b8cc908cb77970967addf39ae1a975d.tar.gz
rust-7f8530f16b8cc908cb77970967addf39ae1a975d.zip
more things are const evaluatable *sparkles*
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs31
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs4
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs1
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/subexprs_are_const_evalutable.rs17
5 files changed, 42 insertions, 13 deletions
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 3fade2c4437..631dcb60594 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -132,7 +132,7 @@ where
         tcx: TyCtxt<'tcx>,
         ct: AbstractConst<'tcx>,
     ) -> ControlFlow<V::BreakTy> {
-        const_evaluatable::walk_abstract_const(tcx, ct, |node| match node {
+        const_evaluatable::walk_abstract_const(tcx, ct, |node| match node.root() {
             ACNode::Leaf(leaf) => {
                 let leaf = leaf.subst(tcx, ct.substs);
                 self.visit_const(leaf)
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index b587ed6487e..3facdd5f84c 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -50,11 +50,24 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                             if b_def == def && b_substs == substs {
                                 debug!("is_const_evaluatable: caller_bound ~~> ok");
                                 return Ok(());
-                            } else if AbstractConst::new(tcx, b_def, b_substs)?
-                                .map_or(false, |b_ct| try_unify(tcx, ct, b_ct))
-                            {
-                                debug!("is_const_evaluatable: abstract_const ~~> ok");
-                                return Ok(());
+                            }
+
+                            if let Some(b_ct) = AbstractConst::new(tcx, b_def, b_substs)? {
+                                // Try to unify with each subtree in the AbstractConst to allow for
+                                // `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
+                                // predicate for `(N + 1) * 2`
+                                let result =
+                                    walk_abstract_const(tcx, b_ct, |b_ct| {
+                                        match try_unify(tcx, ct, b_ct) {
+                                            true => ControlFlow::BREAK,
+                                            false => ControlFlow::CONTINUE,
+                                        }
+                                    });
+
+                                if let ControlFlow::Break(()) = result {
+                                    debug!("is_const_evaluatable: abstract_const ~~> ok");
+                                    return Ok(());
+                                }
                             }
                         }
                         _ => {} // don't care
@@ -78,7 +91,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                     Concrete,
                 }
                 let mut failure_kind = FailureKind::Concrete;
-                walk_abstract_const::<!, _>(tcx, ct, |node| match node {
+                walk_abstract_const::<!, _>(tcx, ct, |node| match node.root() {
                     Node::Leaf(leaf) => {
                         let leaf = leaf.subst(tcx, ct.substs);
                         if leaf.has_infer_types_or_consts() {
@@ -580,15 +593,15 @@ pub fn walk_abstract_const<'tcx, R, F>(
     mut f: F,
 ) -> ControlFlow<R>
 where
-    F: FnMut(Node<'tcx>) -> ControlFlow<R>,
+    F: FnMut(AbstractConst<'tcx>) -> ControlFlow<R>,
 {
     fn recurse<'tcx, R>(
         tcx: TyCtxt<'tcx>,
         ct: AbstractConst<'tcx>,
-        f: &mut dyn FnMut(Node<'tcx>) -> ControlFlow<R>,
+        f: &mut dyn FnMut(AbstractConst<'tcx>) -> ControlFlow<R>,
     ) -> ControlFlow<R> {
+        f(ct)?;
         let root = ct.root();
-        f(root)?;
         match root {
             Node::Leaf(_) => ControlFlow::CONTINUE,
             Node::Binop(_, l, r) => {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index a9723611f81..3852005ee3f 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -828,7 +828,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
             // constants which are not considered const evaluatable.
             use rustc_middle::mir::abstract_const::Node;
             if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
-                const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node {
+                const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
                     Node::Leaf(leaf) => {
                         let leaf = leaf.subst(self.tcx, ct.substs);
                         self.visit_const(leaf)
@@ -849,7 +849,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
                 // take a `ty::Const` instead.
                 use rustc_middle::mir::abstract_const::Node;
                 if let Ok(Some(ct)) = AbstractConst::new(self.tcx, def, substs) {
-                    const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node {
+                    const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
                         Node::Leaf(leaf) => {
                             let leaf = leaf.subst(self.tcx, ct.substs);
                             self.visit_const(leaf)
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs
index 1428f774b0d..4d0b87efc77 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs
+++ b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs
@@ -21,7 +21,6 @@ where
 
 fn substs3<const L: usize>() -> Substs1<{ (L - 1) * 2 }>
 where
-    [(); (L - 1)]: ,
     [(); (L - 1) * 2 + 1]: ,
 {
     substs2::<{ L - 1 }>()
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/subexprs_are_const_evalutable.rs b/src/test/ui/const-generics/const_evaluatable_checked/subexprs_are_const_evalutable.rs
new file mode 100644
index 00000000000..11c0760cdfe
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/subexprs_are_const_evalutable.rs
@@ -0,0 +1,17 @@
+// run-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+fn make_array<const M: usize>() -> [(); M + 1] {
+    [(); M + 1]
+}
+
+fn foo<const N: usize>() -> [(); (N * 2) + 1] {
+    make_array::<{ N * 2 }>()
+}
+
+fn main() {
+    assert_eq!(foo::<10>(), [(); 10 * 2 + 1])
+}
+
+// Tests that N * 2 is considered const_evalutable by appearing as part of the (N * 2) + 1 const