allow unary operations and ignore StorageLive/Dead stmts
This commit is contained in:
parent
5a277822a5
commit
d1294e0ce2
@ -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(
|
||||
|
14
src/test/ui/const-generics/const_evaluatable_checked/unop.rs
Normal file
14
src/test/ui/const-generics/const_evaluatable_checked/unop.rs
Normal 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>();
|
||||
}
|
Loading…
Reference in New Issue
Block a user