Skip to content

Commit f6bab65

Browse files
committed
more things are const evaluatable *sparkles*
1 parent 04caa63 commit f6bab65

File tree

4 files changed

+41
-12
lines changed

4 files changed

+41
-12
lines changed

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,24 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
5050
if b_def == def && b_substs == substs {
5151
debug!("is_const_evaluatable: caller_bound ~~> ok");
5252
return Ok(());
53-
} else if AbstractConst::new(tcx, b_def, b_substs)?
54-
.map_or(false, |b_ct| try_unify(tcx, ct, b_ct))
55-
{
56-
debug!("is_const_evaluatable: abstract_const ~~> ok");
57-
return Ok(());
53+
}
54+
55+
if let Some(b_ct) = AbstractConst::new(tcx, b_def, b_substs)? {
56+
// Try to unify with each subtree in the AbstractConst to allow for
57+
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
58+
// predicate for `(N + 1) * 2`
59+
let result =
60+
walk_abstract_const(tcx, b_ct, |b_ct| {
61+
match try_unify(tcx, ct, b_ct) {
62+
true => ControlFlow::BREAK,
63+
false => ControlFlow::CONTINUE,
64+
}
65+
});
66+
67+
if let ControlFlow::Break(()) = result {
68+
debug!("is_const_evaluatable: abstract_const ~~> ok");
69+
return Ok(());
70+
}
5871
}
5972
}
6073
_ => {} // don't care
@@ -78,7 +91,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
7891
Concrete,
7992
}
8093
let mut failure_kind = FailureKind::Concrete;
81-
walk_abstract_const::<!, _>(tcx, ct, |node| match node {
94+
walk_abstract_const::<!, _>(tcx, ct, |node| match node.root() {
8295
Node::Leaf(leaf) => {
8396
let leaf = leaf.subst(tcx, ct.substs);
8497
if leaf.has_infer_types_or_consts() {
@@ -580,15 +593,15 @@ pub fn walk_abstract_const<'tcx, R, F>(
580593
mut f: F,
581594
) -> ControlFlow<R>
582595
where
583-
F: FnMut(Node<'tcx>) -> ControlFlow<R>,
596+
F: FnMut(AbstractConst<'tcx>) -> ControlFlow<R>,
584597
{
585598
fn recurse<'tcx, R>(
586599
tcx: TyCtxt<'tcx>,
587600
ct: AbstractConst<'tcx>,
588-
f: &mut dyn FnMut(Node<'tcx>) -> ControlFlow<R>,
601+
f: &mut dyn FnMut(AbstractConst<'tcx>) -> ControlFlow<R>,
589602
) -> ControlFlow<R> {
603+
f(ct)?;
590604
let root = ct.root();
591-
f(root)?;
592605
match root {
593606
Node::Leaf(_) => ControlFlow::CONTINUE,
594607
Node::Binop(_, l, r) => {

compiler/rustc_trait_selection/src/traits/object_safety.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
828828
// constants which are not considered const evaluatable.
829829
use rustc_middle::mir::abstract_const::Node;
830830
if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
831-
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node {
831+
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
832832
Node::Leaf(leaf) => {
833833
let leaf = leaf.subst(self.tcx, ct.substs);
834834
self.visit_const(leaf)
@@ -849,7 +849,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
849849
// take a `ty::Const` instead.
850850
use rustc_middle::mir::abstract_const::Node;
851851
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, def, substs) {
852-
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node {
852+
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
853853
Node::Leaf(leaf) => {
854854
let leaf = leaf.subst(self.tcx, ct.substs);
855855
self.visit_const(leaf)

src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ where
2121

2222
fn substs3<const L: usize>() -> Substs1<{ (L - 1) * 2 }>
2323
where
24-
[(); (L - 1)]: ,
2524
[(); (L - 1) * 2 + 1]: ,
2625
{
2726
substs2::<{ L - 1 }>()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// run-pass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
fn make_array<const M: usize>() -> [(); M + 1] {
6+
[(); M + 1]
7+
}
8+
9+
fn foo<const N: usize>() -> [(); (N * 2) + 1] {
10+
make_array::<{ N * 2 }>()
11+
}
12+
13+
fn main() {
14+
assert_eq!(foo::<10>(), [(); 10 * 2 + 1])
15+
}
16+
17+
// Tests that N * 2 is considered const_evalutable by appearing as part of the (N * 2) + 1 const

0 commit comments

Comments
 (0)