diff options
| author | Bastian Kauschke <bastian_kauschke@hotmail.de> | 2020-09-11 10:00:06 +0200 |
|---|---|---|
| committer | Bastian Kauschke <bastian_kauschke@hotmail.de> | 2020-09-18 17:11:34 +0200 |
| commit | d1294e0ce2ce78e4a634fbfa68cb2bc4d50afc6e (patch) | |
| tree | f32d9289e39c862d70cb15bd15b38e3e20118cd5 | |
| parent | 5a277822a536eff72d562e75fb6046add63d4926 (diff) | |
| download | rust-d1294e0ce2ce78e4a634fbfa68cb2bc4d50afc6e.tar.gz rust-d1294e0ce2ce78e4a634fbfa68cb2bc4d50afc6e.zip | |
allow unary operations and ignore StorageLive/Dead stmts
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 27 | ||||
| -rw-r--r-- | src/test/ui/const-generics/const_evaluatable_checked/unop.rs | 14 |
2 files changed, 37 insertions, 4 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 56886aae066..f0e51511732 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -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( diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unop.rs b/src/test/ui/const-generics/const_evaluatable_checked/unop.rs new file mode 100644 index 00000000000..8e0768b1c95 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/unop.rs @@ -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>(); +} |
