diff --git a/compiler/noirc_frontend/src/hir/type_check/errors.rs b/compiler/noirc_frontend/src/hir/type_check/errors.rs index c8842a4084e..234504c67c8 100644 --- a/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -54,7 +54,7 @@ pub enum TypeCheckError { location: Location, }, #[error("Evaluating `{op}` on `{lhs}`, `{rhs}` failed")] - FailingBinaryOp { op: BinaryTypeOperator, lhs: i128, rhs: i128, location: Location }, + FailingBinaryOp { op: BinaryTypeOperator, lhs: String, rhs: String, location: Location }, #[error("Type {typ:?} cannot be used in a {place:?}")] TypeCannotBeUsed { typ: Type, place: &'static str, location: Location }, #[error("Expected type {expected_typ:?} is not the same as {expr_typ:?}")] diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 997011e1d55..d339a7b682e 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -2637,20 +2637,48 @@ impl BinaryTypeOperator { Err(TypeCheckError::ModuloOnFields { lhs: a, rhs: b, location }) } }, - Some(_maximum_size) => { - let a = a.to_i128(); - let b = b.to_i128(); - - let err = TypeCheckError::FailingBinaryOp { op: self, lhs: a, rhs: b, location }; - let result = match self { - BinaryTypeOperator::Addition => a.checked_add(b).ok_or(err)?, - BinaryTypeOperator::Subtraction => a.checked_sub(b).ok_or(err)?, - BinaryTypeOperator::Multiplication => a.checked_mul(b).ok_or(err)?, - BinaryTypeOperator::Division => a.checked_div(b).ok_or(err)?, - BinaryTypeOperator::Modulo => a.checked_rem(b).ok_or(err)?, - }; - - Ok(result.into()) + Some(maximum_size) => { + if maximum_size.to_u128() == u128::MAX { + // For u128 operations we need to use u128 + let a = a.to_u128(); + let b = b.to_u128(); + + let err = TypeCheckError::FailingBinaryOp { + op: self, + lhs: a.to_string(), + rhs: b.to_string(), + location, + }; + let result = match self { + BinaryTypeOperator::Addition => a.checked_add(b).ok_or(err)?, + BinaryTypeOperator::Subtraction => a.checked_sub(b).ok_or(err)?, + BinaryTypeOperator::Multiplication => a.checked_mul(b).ok_or(err)?, + BinaryTypeOperator::Division => a.checked_div(b).ok_or(err)?, + BinaryTypeOperator::Modulo => a.checked_rem(b).ok_or(err)?, + }; + + Ok(result.into()) + } else { + // Every other type first in i128, allowing both positive and negative values + let a = a.to_i128(); + let b = b.to_i128(); + + let err = TypeCheckError::FailingBinaryOp { + op: self, + lhs: a.to_string(), + rhs: b.to_string(), + location, + }; + let result = match self { + BinaryTypeOperator::Addition => a.checked_add(b).ok_or(err)?, + BinaryTypeOperator::Subtraction => a.checked_sub(b).ok_or(err)?, + BinaryTypeOperator::Multiplication => a.checked_mul(b).ok_or(err)?, + BinaryTypeOperator::Division => a.checked_div(b).ok_or(err)?, + BinaryTypeOperator::Modulo => a.checked_rem(b).ok_or(err)?, + }; + + Ok(result.into()) + } } } } diff --git a/compiler/noirc_frontend/src/tests/arithmetic_generics.rs b/compiler/noirc_frontend/src/tests/arithmetic_generics.rs index a10a0489e17..d402dda65b6 100644 --- a/compiler/noirc_frontend/src/tests/arithmetic_generics.rs +++ b/compiler/noirc_frontend/src/tests/arithmetic_generics.rs @@ -1,5 +1,7 @@ #![cfg(test)] +use core::panic; + use acvm::{AcirField, FieldElement}; use crate::assert_no_errors; @@ -93,10 +95,12 @@ fn arithmetic_generics_checked_cast_zeros() { } _ => panic!("unexpected length: {length:?}"), } - assert!(matches!( - err, - TypeCheckError::FailingBinaryOp { op: BinaryTypeOperator::Modulo, lhs: 0, rhs: 0, .. } - )); + let TypeCheckError::FailingBinaryOp { op, lhs, rhs, .. } = err else { + panic!("Expected FailingBinaryOp, but found: {err:?}"); + }; + assert_eq!(op, &BinaryTypeOperator::Modulo); + assert_eq!(lhs, "0"); + assert_eq!(rhs, "0"); } else { panic!("unexpected error: {monomorphization_error:?}"); } diff --git a/test_programs/compile_success_empty/comptime_u128_ops/Nargo.toml b/test_programs/compile_success_empty/comptime_u128_ops/Nargo.toml new file mode 100644 index 00000000000..ee2cc23b465 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_u128_ops/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_u128_ops" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_u128_ops/src/main.nr b/test_programs/compile_success_empty/comptime_u128_ops/src/main.nr new file mode 100644 index 00000000000..fbccef250d2 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_u128_ops/src/main.nr @@ -0,0 +1,19 @@ +fn main() { + comptime { + let y = foo::<340282366920938463463374607431768211455, 1>(); + assert_eq(y.n(), 340282366920938463463374607431768211454); + } +} + +struct T {} + +impl T { + fn n(self) -> u128 { + let _ = self; + N + } +} + +fn foo() -> T { + T {} +} diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/comptime_u128_ops/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/comptime_u128_ops/execute__tests__expanded.snap new file mode 100644 index 00000000000..78ebcde1b9a --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/comptime_u128_ops/execute__tests__expanded.snap @@ -0,0 +1,20 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: expanded_code +--- +fn main() { + () +} + +struct T {} + +impl T { + fn n(self) -> u128 { + let _: Self = self; + N + } +} + +fn foo() -> T { + T:: {} +} diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/comptime_u128_ops/execute__tests__force_brillig_false_inliner_0.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/comptime_u128_ops/execute__tests__force_brillig_false_inliner_0.snap new file mode 100644 index 00000000000..7de940827c8 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/comptime_u128_ops/execute__tests__force_brillig_false_inliner_0.snap @@ -0,0 +1,26 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: artifact +--- +{ + "noir_version": "[noir_version]", + "hash": "[hash]", + "abi": { + "parameters": [], + "return_type": null, + "error_types": {} + }, + "bytecode": [ + "func 0", + "current witness index : _0", + "private parameters indices : []", + "public parameters indices : []", + "return value indices : []" + ], + "debug_symbols": "XY5BCsQwCEXv4rqLWfcqw1BsaosgJtikMITefWyYQOlK/3/6tcJCc9km1jXuML4rzMYivE0SA2aO6m49B+hyykbkFty4byU00gyjFpEBDpTShvaE2mpGc/oagHTx6oErC13d+XGBge158UBjnIX+ci0abjR/Uyf942Qx0FKMrqTGPPsH", + "file_map": {}, + "names": [ + "main" + ], + "brillig_names": [] +}