}
}
+ /// 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 {
}
}
+ /// 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 {
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)?;
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) => {
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(
--- /dev/null
+// 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>();
+}