about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2023-07-04 15:40:15 +0200
committerlcnr <rust@lcnr.de>2023-07-04 15:54:18 +0200
commitabcaf30f9bce3f84f2574184a4bf44d44fd84a7c (patch)
tree0053fa910bbbbf4d4c1b0e85fc85f593ec0ea1f9
parentcd68ead9ecfdb3bfbd65cb5ff444c5eaadd21a4d (diff)
downloadrust-abcaf30f9bce3f84f2574184a4bf44d44fd84a7c.tar.gz
rust-abcaf30f9bce3f84f2574184a4bf44d44fd84a7c.zip
implement `ConstEvaluatable` goals in new solver
we don't yet handle `generic_const_exprs`, someone else
can do that :3
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs37
-rw-r--r--tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr (renamed from tests/ui/const-generics/defaults/default-param-wf-concrete.stderr)2
-rw-r--r--tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr9
-rw-r--r--tests/ui/const-generics/defaults/default-param-wf-concrete.rs3
-rw-r--r--tests/ui/consts/const-len-underflow-separate-spans.next.stderr (renamed from tests/ui/consts/const-len-underflow-separate-spans.stderr)4
-rw-r--r--tests/ui/consts/const-len-underflow-separate-spans.old.stderr15
-rw-r--r--tests/ui/consts/const-len-underflow-separate-spans.rs3
8 files changed, 75 insertions, 9 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 6b7be73b631..034d68e5459 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -425,12 +425,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
                     self.compute_well_formed_goal(Goal { param_env, predicate: arg })
                 }
-                ty::PredicateKind::Ambiguous => {
-                    self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
-                }
-                // FIXME: implement this predicate :)
-                ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(_)) => {
-                    self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
+                    self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
                 }
                 ty::PredicateKind::ConstEquate(_, _) => {
                     bug!("ConstEquate should not be emitted when `-Ztrait-solver=next` is active")
@@ -440,6 +436,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                         param_env,
                         predicate: (lhs, rhs, direction),
                     }),
+                ty::PredicateKind::Ambiguous => {
+                    self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+                }
             }
         } else {
             let kind = self.infcx.instantiate_binder_with_placeholders(kind);
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index f3f78cdf09d..b987a3a3500 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -159,6 +159,43 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
+    fn compute_const_evaluatable_goal(
+        &mut self,
+        Goal { param_env, predicate: ct }: Goal<'tcx, ty::Const<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        match ct.kind() {
+            ty::ConstKind::Unevaluated(uv) => {
+                // We never return `NoSolution` here as `try_const_eval_resolve` emits an
+                // error itself when failing to evaluate, so emitting an additional fulfillment
+                // error in that case is unnecessary noise. This may change in the future once
+                // evaluation failures are allowed to impact selection, e.g. generic const
+                // expressions in impl headers or `where`-clauses.
+
+                // FIXME(generic_const_exprs): Implement handling for generic
+                // const expressions here.
+                if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv, ct.ty()) {
+                    self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                } else {
+                    self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+                }
+            }
+            ty::ConstKind::Infer(_) => {
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+            }
+            ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            }
+            // We can freely ICE here as:
+            // - `Param` gets replaced with a placeholder during canonicalization
+            // - `Bound` cannot exist as we don't have a binder around the self Type
+            // - `Expr` is part of `feature(generic_const_exprs)` and is not implemented yet
+            ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Expr(_) => {
+                bug!("unexpect const kind: {:?}", ct)
+            }
+        }
+    }
+
     #[instrument(level = "debug", skip(self), ret)]
     fn compute_const_arg_has_type_goal(
         &mut self,
diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr
index e8ebddade5c..4259ce2b626 100644
--- a/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr
+++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/default-param-wf-concrete.rs:1:28
+  --> $DIR/default-param-wf-concrete.rs:4:28
    |
 LL | struct Foo<const N: u8 = { 255 + 1 }>;
    |                            ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr
new file mode 100644
index 00000000000..4259ce2b626
--- /dev/null
+++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/default-param-wf-concrete.rs:4:28
+   |
+LL | struct Foo<const N: u8 = { 255 + 1 }>;
+   |                            ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.rs b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs
index 41a52c7eb0d..09a00dd8e70 100644
--- a/tests/ui/const-generics/defaults/default-param-wf-concrete.rs
+++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs
@@ -1,3 +1,6 @@
+// revisions: old next
+//[next] compile-flags: -Ztrait-solver=next
+
 struct Foo<const N: u8 = { 255 + 1 }>;
 //~^ ERROR evaluation of constant value failed
 fn main() {}
diff --git a/tests/ui/consts/const-len-underflow-separate-spans.stderr b/tests/ui/consts/const-len-underflow-separate-spans.next.stderr
index 269553631cc..d9208d0706a 100644
--- a/tests/ui/consts/const-len-underflow-separate-spans.stderr
+++ b/tests/ui/consts/const-len-underflow-separate-spans.next.stderr
@@ -1,11 +1,11 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-len-underflow-separate-spans.rs:7:20
+  --> $DIR/const-len-underflow-separate-spans.rs:10:20
    |
 LL | const LEN: usize = ONE - TWO;
    |                    ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow
 
 note: erroneous constant used
-  --> $DIR/const-len-underflow-separate-spans.rs:11:17
+  --> $DIR/const-len-underflow-separate-spans.rs:14:17
    |
 LL |     let a: [i8; LEN] = unimplemented!();
    |                 ^^^
diff --git a/tests/ui/consts/const-len-underflow-separate-spans.old.stderr b/tests/ui/consts/const-len-underflow-separate-spans.old.stderr
new file mode 100644
index 00000000000..d9208d0706a
--- /dev/null
+++ b/tests/ui/consts/const-len-underflow-separate-spans.old.stderr
@@ -0,0 +1,15 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-len-underflow-separate-spans.rs:10:20
+   |
+LL | const LEN: usize = ONE - TWO;
+   |                    ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow
+
+note: erroneous constant used
+  --> $DIR/const-len-underflow-separate-spans.rs:14:17
+   |
+LL |     let a: [i8; LEN] = unimplemented!();
+   |                 ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-len-underflow-separate-spans.rs b/tests/ui/consts/const-len-underflow-separate-spans.rs
index 4544c8876ae..55704b64154 100644
--- a/tests/ui/consts/const-len-underflow-separate-spans.rs
+++ b/tests/ui/consts/const-len-underflow-separate-spans.rs
@@ -2,6 +2,9 @@
 // spot (where the underflow occurred), while also providing the
 // overall context for what caused the evaluation.
 
+// revisions: old next
+//[next] compile-flags: -Ztrait-solver=next
+
 const ONE: usize = 1;
 const TWO: usize = 2;
 const LEN: usize = ONE - TWO;