From b3ddf10a2cbb80e88821baf7d76c478c3b98b3ea Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:31:23 +0000 Subject: [PATCH] fix: allow performing bitwise NOT on unsigned integers (#4229) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description ## Problem\* Resolves ## Summary\* Currently running `bit_not` results in the output ``` $ nargo info --show-ssa error: u8 cannot be used in a unary operation ┌─ /home/tom/Programming/aztec/noir/test_programs/execution_success/bit_not/src/main.nr:3:30 │ 3 │ let not_four_as_u8: u8 = !four_as_u8; │ ----------- │ error: u32 cannot be used in a unary operation ┌─ /home/tom/Programming/aztec/noir/test_programs/execution_success/bit_not/src/main.nr:6:32 │ 6 │ let not_four_as_u32: u32 = !four_as_u32; │ ------------ │ ``` We're unable to perform bitwise nots for unsigned integers (signed is fine). This PR loosens the check being applied in `lint_overflowing_uint` so that it only errors for using an unary `-`. ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --- compiler/noirc_frontend/src/hir/type_check/stmt.rs | 13 ++++++++++--- test_programs/execution_success/bit_not/Nargo.toml | 7 +++++++ test_programs/execution_success/bit_not/Prover.toml | 1 + test_programs/execution_success/bit_not/src/main.nr | 8 ++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 test_programs/execution_success/bit_not/Nargo.toml create mode 100644 test_programs/execution_success/bit_not/Prover.toml create mode 100644 test_programs/execution_success/bit_not/src/main.nr diff --git a/compiler/noirc_frontend/src/hir/type_check/stmt.rs b/compiler/noirc_frontend/src/hir/type_check/stmt.rs index a38a16a6580..76bd064bf83 100644 --- a/compiler/noirc_frontend/src/hir/type_check/stmt.rs +++ b/compiler/noirc_frontend/src/hir/type_check/stmt.rs @@ -8,6 +8,7 @@ use crate::hir_def::stmt::{ }; use crate::hir_def::types::Type; use crate::node_interner::{DefinitionId, ExprId, StmtId}; +use crate::UnaryOp; use super::errors::{Source, TypeCheckError}; use super::TypeChecker; @@ -361,9 +362,15 @@ impl<'interner> TypeChecker<'interner> { }; }; } - HirExpression::Prefix(_) => self - .errors - .push(TypeCheckError::InvalidUnaryOp { kind: annotated_type.to_string(), span }), + HirExpression::Prefix(expr) => { + self.lint_overflowing_uint(&expr.rhs, annotated_type); + if matches!(expr.operator, UnaryOp::Minus) { + self.errors.push(TypeCheckError::InvalidUnaryOp { + kind: "annotated_type".to_string(), + span, + }); + } + } HirExpression::Infix(expr) => { self.lint_overflowing_uint(&expr.lhs, annotated_type); self.lint_overflowing_uint(&expr.rhs, annotated_type); diff --git a/test_programs/execution_success/bit_not/Nargo.toml b/test_programs/execution_success/bit_not/Nargo.toml new file mode 100644 index 00000000000..e89a338595b --- /dev/null +++ b/test_programs/execution_success/bit_not/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bit_not" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/execution_success/bit_not/Prover.toml b/test_programs/execution_success/bit_not/Prover.toml new file mode 100644 index 00000000000..b4bcbcec177 --- /dev/null +++ b/test_programs/execution_success/bit_not/Prover.toml @@ -0,0 +1 @@ +four_as_u32 = 4 diff --git a/test_programs/execution_success/bit_not/src/main.nr b/test_programs/execution_success/bit_not/src/main.nr new file mode 100644 index 00000000000..30b78d330ce --- /dev/null +++ b/test_programs/execution_success/bit_not/src/main.nr @@ -0,0 +1,8 @@ +fn main(four_as_u32: u32) { + let four_as_u8: u8 = 4; + let not_four_as_u8: u8 = !four_as_u8; + assert_eq(not_four_as_u8, 251); + + let not_four_as_u32: u32 = !four_as_u32; + assert_eq(not_four_as_u32, 4294967291); +}