allow unary operations and ignore StorageLive/Dead stmts

This commit is contained in:
Bastian Kauschke 2020-09-11 10:00:06 +02:00
parent 5a277822a5
commit d1294e0ce2
2 changed files with 37 additions and 4 deletions

View File

@ -174,6 +174,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
}
}
/// We do not allow all binary operations in abstract consts, so filter disallowed ones.
fn check_binop(op: mir::BinOp) -> bool {
use mir::BinOp::*;
match op {
@ -183,6 +184,15 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
}
}
/// While we currently allow all unary operations, we still want to explicitly guard against
/// future changes here.
fn check_unop(op: mir::UnOp) -> bool {
use mir::UnOp::*;
match op {
Not | Neg => true,
}
}
fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Option<()> {
debug!("AbstractConstBuilder: stmt={:?}", stmt);
match stmt.kind {
@ -191,6 +201,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
match *rvalue {
Rvalue::Use(ref operand) => {
self.locals[local] = self.operand_to_node(operand)?;
Some(())
}
Rvalue::BinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
let lhs = self.operand_to_node(lhs)?;
@ -198,6 +209,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
self.locals[local] = self.nodes.push(Node::Binop(op, lhs, rhs));
if op.is_checkable() {
bug!("unexpected unchecked checkable binary operation");
} else {
Some(())
}
}
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
@ -205,14 +218,20 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
let rhs = self.operand_to_node(rhs)?;
self.locals[local] = self.nodes.push(Node::Binop(op, lhs, rhs));
self.checked_op_locals.insert(local);
Some(())
}
_ => return None,
Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => {
let operand = self.operand_to_node(operand)?;
self.locals[local] = self.nodes.push(Node::UnaryOp(op, operand));
Some(())
}
_ => None,
}
}
_ => return None,
// These are not actually relevant for us here, so we can ignore them.
StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => Some(()),
_ => None,
}
Some(())
}
fn build_terminator(

View File

@ -0,0 +1,14 @@
// run-pass
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]
struct Foo<const B: bool>;
fn test<const N: usize>() -> Foo<{ !(N > 10) }> where Foo<{ !(N > 10) }>: Sized {
Foo
}
fn main() {
let _: Foo<false> = test::<12>();
let _: Foo<true> = test::<9>();
}