Rollup merge of #81577 - BoxyUwU:subexpr_const_evaluatable, r=oli-obk
const_evaluatable: consider sub-expressions to be evaluatable see [zulip topic](https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/const_evaluatable.3A.20subexpressions) for more info cc `@lcnr` r? `@oli-obk`
This commit is contained in:
commit
efec2bbbce
@ -132,7 +132,7 @@ where
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ct: AbstractConst<'tcx>,
|
ct: AbstractConst<'tcx>,
|
||||||
) -> ControlFlow<V::BreakTy> {
|
) -> 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) => {
|
ACNode::Leaf(leaf) => {
|
||||||
let leaf = leaf.subst(tcx, ct.substs);
|
let leaf = leaf.subst(tcx, ct.substs);
|
||||||
self.visit_const(leaf)
|
self.visit_const(leaf)
|
||||||
|
@ -50,11 +50,24 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
|||||||
if b_def == def && b_substs == substs {
|
if b_def == def && b_substs == substs {
|
||||||
debug!("is_const_evaluatable: caller_bound ~~> ok");
|
debug!("is_const_evaluatable: caller_bound ~~> ok");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if AbstractConst::new(tcx, b_def, b_substs)?
|
}
|
||||||
.map_or(false, |b_ct| try_unify(tcx, ct, b_ct))
|
|
||||||
{
|
if let Some(b_ct) = AbstractConst::new(tcx, b_def, b_substs)? {
|
||||||
debug!("is_const_evaluatable: abstract_const ~~> ok");
|
// Try to unify with each subtree in the AbstractConst to allow for
|
||||||
return Ok(());
|
// `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
|
_ => {} // don't care
|
||||||
@ -78,7 +91,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
|||||||
Concrete,
|
Concrete,
|
||||||
}
|
}
|
||||||
let mut failure_kind = FailureKind::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) => {
|
Node::Leaf(leaf) => {
|
||||||
let leaf = leaf.subst(tcx, ct.substs);
|
let leaf = leaf.subst(tcx, ct.substs);
|
||||||
if leaf.has_infer_types_or_consts() {
|
if leaf.has_infer_types_or_consts() {
|
||||||
@ -580,15 +593,15 @@ pub fn walk_abstract_const<'tcx, R, F>(
|
|||||||
mut f: F,
|
mut f: F,
|
||||||
) -> ControlFlow<R>
|
) -> ControlFlow<R>
|
||||||
where
|
where
|
||||||
F: FnMut(Node<'tcx>) -> ControlFlow<R>,
|
F: FnMut(AbstractConst<'tcx>) -> ControlFlow<R>,
|
||||||
{
|
{
|
||||||
fn recurse<'tcx, R>(
|
fn recurse<'tcx, R>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ct: AbstractConst<'tcx>,
|
ct: AbstractConst<'tcx>,
|
||||||
f: &mut dyn FnMut(Node<'tcx>) -> ControlFlow<R>,
|
f: &mut dyn FnMut(AbstractConst<'tcx>) -> ControlFlow<R>,
|
||||||
) -> ControlFlow<R> {
|
) -> ControlFlow<R> {
|
||||||
|
f(ct)?;
|
||||||
let root = ct.root();
|
let root = ct.root();
|
||||||
f(root)?;
|
|
||||||
match root {
|
match root {
|
||||||
Node::Leaf(_) => ControlFlow::CONTINUE,
|
Node::Leaf(_) => ControlFlow::CONTINUE,
|
||||||
Node::Binop(_, l, r) => {
|
Node::Binop(_, l, r) => {
|
||||||
|
@ -828,7 +828,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
|
|||||||
// constants which are not considered const evaluatable.
|
// constants which are not considered const evaluatable.
|
||||||
use rustc_middle::mir::abstract_const::Node;
|
use rustc_middle::mir::abstract_const::Node;
|
||||||
if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
|
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) => {
|
Node::Leaf(leaf) => {
|
||||||
let leaf = leaf.subst(self.tcx, ct.substs);
|
let leaf = leaf.subst(self.tcx, ct.substs);
|
||||||
self.visit_const(leaf)
|
self.visit_const(leaf)
|
||||||
@ -849,7 +849,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
|
|||||||
// take a `ty::Const` instead.
|
// take a `ty::Const` instead.
|
||||||
use rustc_middle::mir::abstract_const::Node;
|
use rustc_middle::mir::abstract_const::Node;
|
||||||
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, def, substs) {
|
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) => {
|
Node::Leaf(leaf) => {
|
||||||
let leaf = leaf.subst(self.tcx, ct.substs);
|
let leaf = leaf.subst(self.tcx, ct.substs);
|
||||||
self.visit_const(leaf)
|
self.visit_const(leaf)
|
||||||
|
@ -21,7 +21,6 @@ where
|
|||||||
|
|
||||||
fn substs3<const L: usize>() -> Substs1<{ (L - 1) * 2 }>
|
fn substs3<const L: usize>() -> Substs1<{ (L - 1) * 2 }>
|
||||||
where
|
where
|
||||||
[(); (L - 1)]: ,
|
|
||||||
[(); (L - 1) * 2 + 1]: ,
|
[(); (L - 1) * 2 + 1]: ,
|
||||||
{
|
{
|
||||||
substs2::<{ L - 1 }>()
|
substs2::<{ L - 1 }>()
|
||||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user