Skip to content

Commit

Permalink
implement ConstEvaluatable goals in new solver
Browse files Browse the repository at this point in the history
we don't yet handle `generic_const_exprs`, someone else
can do that :3
  • Loading branch information
lcnr committed Jul 4, 2023
1 parent cd68ead commit abcaf30
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 9 deletions.
11 changes: 5 additions & 6 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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);
Expand Down
37 changes: 37 additions & 0 deletions compiler/rustc_trait_selection/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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`.
3 changes: 3 additions & 0 deletions tests/ui/const-generics/defaults/default-param-wf-concrete.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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!();
| ^^^
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/consts/const-len-underflow-separate-spans.old.stderr
Original file line number Diff line number Diff line change
@@ -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`.
3 changes: 3 additions & 0 deletions tests/ui/consts/const-len-underflow-separate-spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit abcaf30

Please sign in to comment.