Support as casts in abstract consts
This commit is contained in:
parent
dda4a881e0
commit
8e7299dfcd
7 changed files with 66 additions and 14 deletions
|
@ -1,6 +1,6 @@
|
||||||
//! A subset of a mir body used for const evaluatability checking.
|
//! A subset of a mir body used for const evaluatability checking.
|
||||||
use crate::mir;
|
use crate::mir::{self, CastKind};
|
||||||
use crate::ty;
|
use crate::ty::{self, Ty};
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
rustc_index::newtype_index! {
|
||||||
/// An index into an `AbstractConst`.
|
/// An index into an `AbstractConst`.
|
||||||
|
@ -17,6 +17,7 @@ pub enum Node<'tcx> {
|
||||||
Binop(mir::BinOp, NodeId, NodeId),
|
Binop(mir::BinOp, NodeId, NodeId),
|
||||||
UnaryOp(mir::UnOp, NodeId),
|
UnaryOp(mir::UnOp, NodeId),
|
||||||
FunctionCall(NodeId, &'tcx [NodeId]),
|
FunctionCall(NodeId, &'tcx [NodeId]),
|
||||||
|
Cast(CastKind, NodeId, Ty<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||||
|
|
|
@ -156,9 +156,10 @@ where
|
||||||
let leaf = leaf.subst(tcx, ct.substs);
|
let leaf = leaf.subst(tcx, ct.substs);
|
||||||
self.visit_const(leaf)
|
self.visit_const(leaf)
|
||||||
}
|
}
|
||||||
ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
|
ACNode::Binop(..)
|
||||||
ControlFlow::CONTINUE
|
| ACNode::UnaryOp(..)
|
||||||
}
|
| ACNode::FunctionCall(_, _)
|
||||||
|
| ACNode::Cast(_, _, _) => ControlFlow::CONTINUE,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,9 +97,10 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||||
|
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {
|
Node::Binop(_, _, _)
|
||||||
ControlFlow::CONTINUE
|
| Node::UnaryOp(_, _)
|
||||||
}
|
| Node::FunctionCall(_, _)
|
||||||
|
| Node::Cast(_, _, _) => ControlFlow::CONTINUE,
|
||||||
});
|
});
|
||||||
|
|
||||||
match failure_kind {
|
match failure_kind {
|
||||||
|
@ -304,6 +305,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
self.nodes[func].used = true;
|
self.nodes[func].used = true;
|
||||||
nodes.iter().for_each(|&n| self.nodes[n].used = true);
|
nodes.iter().for_each(|&n| self.nodes[n].used = true);
|
||||||
}
|
}
|
||||||
|
Node::Cast(_, operand, _) => {
|
||||||
|
self.nodes[operand].used = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nodes start as unused.
|
// Nodes start as unused.
|
||||||
|
@ -408,6 +412,12 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span);
|
self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Rvalue::Cast(cast_kind, ref operand, ty) => {
|
||||||
|
let operand = self.operand_to_node(span, operand)?;
|
||||||
|
self.locals[local] =
|
||||||
|
self.add_node(Node::Cast(cast_kind, operand, ty), span);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
_ => self.error(Some(span), "unsupported rvalue")?,
|
_ => self.error(Some(span), "unsupported rvalue")?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -594,6 +604,7 @@ where
|
||||||
recurse(tcx, ct.subtree(func), f)?;
|
recurse(tcx, ct.subtree(func), f)?;
|
||||||
args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f))
|
args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f))
|
||||||
}
|
}
|
||||||
|
Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,6 +687,11 @@ pub(super) fn try_unify<'tcx>(
|
||||||
&& iter::zip(a_args, b_args)
|
&& iter::zip(a_args, b_args)
|
||||||
.all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
|
.all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
|
||||||
}
|
}
|
||||||
|
(Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty))
|
||||||
|
if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) =>
|
||||||
|
{
|
||||||
|
try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand))
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -838,9 +838,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
|
||||||
let leaf = leaf.subst(self.tcx, ct.substs);
|
let leaf = leaf.subst(self.tcx, ct.substs);
|
||||||
self.visit_const(leaf)
|
self.visit_const(leaf)
|
||||||
}
|
}
|
||||||
Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
|
Node::Binop(..)
|
||||||
ControlFlow::CONTINUE
|
| Node::UnaryOp(..)
|
||||||
}
|
| Node::FunctionCall(_, _)
|
||||||
|
| Node::Cast(_, _, _) => ControlFlow::CONTINUE,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
|
@ -859,9 +860,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
|
||||||
let leaf = leaf.subst(self.tcx, ct.substs);
|
let leaf = leaf.subst(self.tcx, ct.substs);
|
||||||
self.visit_const(leaf)
|
self.visit_const(leaf)
|
||||||
}
|
}
|
||||||
Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
|
Node::Binop(..)
|
||||||
ControlFlow::CONTINUE
|
| Node::UnaryOp(..)
|
||||||
}
|
| Node::FunctionCall(_, _)
|
||||||
|
| Node::Cast(_, _, _) => ControlFlow::CONTINUE,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#![feature(const_evaluatable_checked, const_generics)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
trait Evaluatable<const N: u128> {}
|
||||||
|
impl<const N: u128> Evaluatable<N> for () {}
|
||||||
|
|
||||||
|
struct Foo<const N: u8>([u8; N as usize])
|
||||||
|
//~^ Error: unconstrained generic constant
|
||||||
|
//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:`
|
||||||
|
where
|
||||||
|
(): Evaluatable<{N as u128}>;
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,10 @@
|
||||||
|
error: unconstrained generic constant
|
||||||
|
--> $DIR/abstract-const-as-cast-2.rs:7:25
|
||||||
|
|
|
||||||
|
LL | struct Foo<const N: u8>([u8; N as usize])
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: try adding a `where` bound using this expression: `where [(); N as usize]:`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// check-pass
|
||||||
|
#![feature(const_evaluatable_checked, const_generics)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
struct Foo<const N: u8>([u8; N as usize])
|
||||||
|
where
|
||||||
|
[(); N as usize]:;
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue