From 3b699d6b92b51efbd040e1ca686c9cea94cd006b Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 2 Feb 2024 11:09:54 +0000 Subject: [PATCH 1/5] feat: add warnings for usage of restricted bit sizes --- compiler/noirc_frontend/src/parser/errors.rs | 9 ++++ compiler/noirc_frontend/src/parser/parser.rs | 15 ++++++- noir_stdlib/src/cmp.nr | 26 ----------- noir_stdlib/src/convert.nr | 9 ---- noir_stdlib/src/default.nr | 2 - noir_stdlib/src/ops.nr | 20 --------- .../brillig_cast/src/main.nr | 26 ++++------- .../brillig_modulo/src/main.nr | 8 ++-- .../execution_success/5_over/src/main.nr | 4 +- .../bit_shifts_comptime/src/main.nr | 2 +- .../src/main.nr | 8 ++-- .../execution_success/regression/src/main.nr | 43 ++++++++++++++----- 12 files changed, 76 insertions(+), 96 deletions(-) diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index 5c869ff4719..9158c68db72 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -40,6 +40,8 @@ pub enum ParserErrorReason { NoFunctionAttributesAllowedOnStruct, #[error("Assert statements can only accept string literals")] AssertMessageNotString, + #[error("Integer bit size {0} won't be supported")] + DeprecatedBitSize(u32), #[error("{0}")] Lexer(LexerErrorKind), } @@ -130,6 +132,8 @@ impl std::fmt::Display for ParserError { } } +pub(crate) static ALLOWED_INTEGER_BIT_SIZES: &[u32] = &[1, 8, 32, 64]; + impl From for Diagnostic { fn from(error: ParserError) -> Diagnostic { match error.reason { @@ -145,6 +149,11 @@ impl From for Diagnostic { "The 'comptime' keyword has been deprecated. It can be removed without affecting your program".into(), error.span, ), + ParserErrorReason::DeprecatedBitSize(bit_size) => Diagnostic::simple_warning( + format!("Use of deprecated bit size {}", bit_size), + format!("Bit sizes for integers will be restricted to {}", ALLOWED_INTEGER_BIT_SIZES.iter().map(|n| n.to_string()).collect::>().join(", ")), + error.span, + ), ParserErrorReason::ExperimentalFeature(_) => Diagnostic::simple_warning( reason.to_string(), "".into(), diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 1bdb276d4fb..1f41a29dd4f 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -23,6 +23,7 @@ //! prevent other parsers from being tried afterward since there is no longer an error. Thus, they should //! be limited to cases like the above `fn` example where it is clear we shouldn't back out of the //! current parser to try alternative parsers in a `choice` expression. +use super::errors::ALLOWED_INTEGER_BIT_SIZES; use super::{ foldl_with_span, labels::ParsingRuleLabel, parameter_name_recovery, parameter_recovery, parenthesized, then_commit, then_commit_ignore, top_level_statement_recovery, ExprParser, @@ -35,7 +36,7 @@ use crate::ast::{ }; use crate::lexer::Lexer; use crate::parser::{force, ignore_then_commit, statement_recovery}; -use crate::token::{Attribute, Attributes, Keyword, SecondaryAttribute, Token, TokenKind}; +use crate::token::{Attribute, Attributes, IntType, Keyword, SecondaryAttribute, Token, TokenKind}; use crate::{ BinaryOp, BinaryOpKind, BlockExpression, ConstrainKind, ConstrainStatement, Distinctness, ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, FunctionVisibility, Ident, @@ -1092,6 +1093,18 @@ fn int_type() -> impl NoirParser { Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) } })) + .validate(|int_type, span, emit| { + let bit_size = match int_type.1 { + IntType::Signed(bit_size) | IntType::Unsigned(bit_size) => bit_size, + }; + if !ALLOWED_INTEGER_BIT_SIZES.contains(&bit_size) { + emit(ParserError::with_reason( + ParserErrorReason::DeprecatedBitSize(bit_size), + span, + )); + } + int_type + }) .map_with_span(|(_, token), span| UnresolvedTypeData::from_int_token(token).with_span(span)) } diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr index b3de3e2658e..38316e5d6a8 100644 --- a/noir_stdlib/src/cmp.nr +++ b/noir_stdlib/src/cmp.nr @@ -8,12 +8,10 @@ impl Eq for Field { fn eq(self, other: Field) -> bool { self == other } } impl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } } impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } -impl Eq for u16 { fn eq(self, other: u16) -> bool { self == other } } impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } impl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } } impl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } } -impl Eq for i16 { fn eq(self, other: i16) -> bool { self == other } } impl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } } impl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } } @@ -111,18 +109,6 @@ impl Ord for u8 { } } -impl Ord for u16 { - fn cmp(self, other: u16) -> Ordering { - if self < other { - Ordering::less() - } else if self > other { - Ordering::greater() - } else { - Ordering::equal() - } - } -} - impl Ord for u32 { fn cmp(self, other: u32) -> Ordering { if self < other { @@ -159,18 +145,6 @@ impl Ord for i8 { } } -impl Ord for i16 { - fn cmp(self, other: i16) -> Ordering { - if self < other { - Ordering::less() - } else if self > other { - Ordering::greater() - } else { - Ordering::equal() - } - } -} - impl Ord for i32 { fn cmp(self, other: i32) -> Ordering { if self < other { diff --git a/noir_stdlib/src/convert.nr b/noir_stdlib/src/convert.nr index 814f63f1cde..00ac0a0fd8c 100644 --- a/noir_stdlib/src/convert.nr +++ b/noir_stdlib/src/convert.nr @@ -24,37 +24,28 @@ impl Into for U where T: From { // docs:start:from-impls // Unsigned integers -impl From for u16 { fn from(value: u8) -> u16 { value as u16 } } impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } -impl From for u32 { fn from(value: u16) -> u32 { value as u32 } } impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u16) -> u64 { value as u64 } } impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } impl From for Field { fn from(value: u8) -> Field { value as Field } } -impl From for Field { fn from(value: u16) -> Field { value as Field } } impl From for Field { fn from(value: u32) -> Field { value as Field } } impl From for Field { fn from(value: u64) -> Field { value as Field } } // Signed integers -impl From for i16 { fn from(value: i8) -> i16 { value as i16 } } impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } -impl From for i32 { fn from(value: i16) -> i32 { value as i32 } } impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i16) -> i64 { value as i64 } } impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } // Booleans impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } -impl From for u16 { fn from(value: bool) -> u16 { value as u16 } } impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } -impl From for i16 { fn from(value: bool) -> i16 { value as i16 } } impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } impl From for Field { fn from(value: bool) -> Field { value as Field } } diff --git a/noir_stdlib/src/default.nr b/noir_stdlib/src/default.nr index ba6412a834f..32c4f3f3b48 100644 --- a/noir_stdlib/src/default.nr +++ b/noir_stdlib/src/default.nr @@ -7,12 +7,10 @@ trait Default { impl Default for Field { fn default() -> Field { 0 } } impl Default for u8 { fn default() -> u8 { 0 } } -impl Default for u16 { fn default() -> u16 { 0 } } impl Default for u32 { fn default() -> u32 { 0 } } impl Default for u64 { fn default() -> u64 { 0 } } impl Default for i8 { fn default() -> i8 { 0 } } -impl Default for i16 { fn default() -> i16 { 0 } } impl Default for i32 { fn default() -> i32 { 0 } } impl Default for i64 { fn default() -> i64 { 0 } } diff --git a/noir_stdlib/src/ops.nr b/noir_stdlib/src/ops.nr index 50386290b8e..e561265629e 100644 --- a/noir_stdlib/src/ops.nr +++ b/noir_stdlib/src/ops.nr @@ -7,12 +7,10 @@ trait Add { impl Add for Field { fn add(self, other: Field) -> Field { self + other } } impl Add for u8 { fn add(self, other: u8) -> u8 { self + other } } -impl Add for u16 { fn add(self, other: u16) -> u16 { self + other } } impl Add for u32 { fn add(self, other: u32) -> u32 { self + other } } impl Add for u64 { fn add(self, other: u64) -> u64 { self + other } } impl Add for i8 { fn add(self, other: i8) -> i8 { self + other } } -impl Add for i16 { fn add(self, other: i16) -> i16 { self + other } } impl Add for i32 { fn add(self, other: i32) -> i32 { self + other } } impl Add for i64 { fn add(self, other: i64) -> i64 { self + other } } @@ -25,12 +23,10 @@ trait Sub { impl Sub for Field { fn sub(self, other: Field) -> Field { self - other } } impl Sub for u8 { fn sub(self, other: u8) -> u8 { self - other } } -impl Sub for u16 { fn sub(self, other: u16) -> u16 { self - other } } impl Sub for u32 { fn sub(self, other: u32) -> u32 { self - other } } impl Sub for u64 { fn sub(self, other: u64) -> u64 { self - other } } impl Sub for i8 { fn sub(self, other: i8) -> i8 { self - other } } -impl Sub for i16 { fn sub(self, other: i16) -> i16 { self - other } } impl Sub for i32 { fn sub(self, other: i32) -> i32 { self - other } } impl Sub for i64 { fn sub(self, other: i64) -> i64 { self - other } } @@ -43,12 +39,10 @@ trait Mul { impl Mul for Field { fn mul(self, other: Field) -> Field { self * other } } impl Mul for u8 { fn mul(self, other: u8) -> u8 { self * other } } -impl Mul for u16 { fn mul(self, other: u16) -> u16 { self * other } } impl Mul for u32 { fn mul(self, other: u32) -> u32 { self * other } } impl Mul for u64 { fn mul(self, other: u64) -> u64 { self * other } } impl Mul for i8 { fn mul(self, other: i8) -> i8 { self * other } } -impl Mul for i16 { fn mul(self, other: i16) -> i16 { self * other } } impl Mul for i32 { fn mul(self, other: i32) -> i32 { self * other } } impl Mul for i64 { fn mul(self, other: i64) -> i64 { self * other } } @@ -61,12 +55,10 @@ trait Div { impl Div for Field { fn div(self, other: Field) -> Field { self / other } } impl Div for u8 { fn div(self, other: u8) -> u8 { self / other } } -impl Div for u16 { fn div(self, other: u16) -> u16 { self / other } } impl Div for u32 { fn div(self, other: u32) -> u32 { self / other } } impl Div for u64 { fn div(self, other: u64) -> u64 { self / other } } impl Div for i8 { fn div(self, other: i8) -> i8 { self / other } } -impl Div for i16 { fn div(self, other: i16) -> i16 { self / other } } impl Div for i32 { fn div(self, other: i32) -> i32 { self / other } } impl Div for i64 { fn div(self, other: i64) -> i64 { self / other } } @@ -77,12 +69,10 @@ trait Rem{ // docs:end:rem-trait impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } @@ -95,12 +85,10 @@ trait BitOr { impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } @@ -113,12 +101,10 @@ trait BitAnd { impl BitAnd for bool { fn bitand(self, other: bool) -> bool { self & other } } impl BitAnd for u8 { fn bitand(self, other: u8) -> u8 { self & other } } -impl BitAnd for u16 { fn bitand(self, other: u16) -> u16 { self & other } } impl BitAnd for u32 { fn bitand(self, other: u32) -> u32 { self & other } } impl BitAnd for u64 { fn bitand(self, other: u64) -> u64 { self & other } } impl BitAnd for i8 { fn bitand(self, other: i8) -> i8 { self & other } } -impl BitAnd for i16 { fn bitand(self, other: i16) -> i16 { self & other } } impl BitAnd for i32 { fn bitand(self, other: i32) -> i32 { self & other } } impl BitAnd for i64 { fn bitand(self, other: i64) -> i64 { self & other } } @@ -131,12 +117,10 @@ trait BitXor { impl BitXor for bool { fn bitxor(self, other: bool) -> bool { self ^ other } } impl BitXor for u8 { fn bitxor(self, other: u8) -> u8 { self ^ other } } -impl BitXor for u16 { fn bitxor(self, other: u16) -> u16 { self ^ other } } impl BitXor for u32 { fn bitxor(self, other: u32) -> u32 { self ^ other } } impl BitXor for u64 { fn bitxor(self, other: u64) -> u64 { self ^ other } } impl BitXor for i8 { fn bitxor(self, other: i8) -> i8 { self ^ other } } -impl BitXor for i16 { fn bitxor(self, other: i16) -> i16 { self ^ other } } impl BitXor for i32 { fn bitxor(self, other: i32) -> i32 { self ^ other } } impl BitXor for i64 { fn bitxor(self, other: i64) -> i64 { self ^ other } } @@ -147,13 +131,11 @@ trait Shl { // docs:end:shl-trait impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } // Bit shifting is not currently supported for signed integer types // impl Shl for i8 { fn shl(self, other: i8) -> i8 { self << other } } -// impl Shl for i16 { fn shl(self, other: i16) -> i16 { self << other } } // impl Shl for i32 { fn shl(self, other: i32) -> i32 { self << other } } // impl Shl for i64 { fn shl(self, other: i64) -> i64 { self << other } } @@ -164,12 +146,10 @@ trait Shr { // docs:end:shr-trait impl Shr for u8 { fn shr(self, other: u8) -> u8 { self >> other } } -impl Shr for u16 { fn shr(self, other: u16) -> u16 { self >> other } } impl Shr for u32 { fn shr(self, other: u32) -> u32 { self >> other } } impl Shr for u64 { fn shr(self, other: u64) -> u64 { self >> other } } // Bit shifting is not currently supported for signed integer types // impl Shr for i8 { fn shr(self, other: i8) -> i8 { self >> other } } -// impl Shr for i16 { fn shr(self, other: i16) -> i16 { self >> other } } // impl Shr for i32 { fn shr(self, other: i32) -> i32 { self >> other } } // impl Shr for i64 { fn shr(self, other: i64) -> i64 { self >> other } } diff --git a/test_programs/compile_success_empty/brillig_cast/src/main.nr b/test_programs/compile_success_empty/brillig_cast/src/main.nr index 3ba29b52982..ecb832468ba 100644 --- a/test_programs/compile_success_empty/brillig_cast/src/main.nr +++ b/test_programs/compile_success_empty/brillig_cast/src/main.nr @@ -17,33 +17,25 @@ unconstrained fn bool_casts() { unconstrained fn field_casts() { assert(5 as u8 as Field == 5); - assert(16 as u4 as Field == 0); + assert(256 as u8 as Field == 0); } unconstrained fn uint_casts() { - let x: u32 = 100; - assert(x as u2 == 0); - assert(x as u4 == 4); - assert(x as u6 == 36); - assert(x as u8 == 100); - assert(x as u64 == 100); - assert(x as u126 == 100); + let x: u32 = 300; + assert(x as u8 == 44); + assert(x as u32 == 300); + assert(x as u64 == 300); } unconstrained fn int_casts() { - let x: i32 = 100; - assert(x as i2 == 0); - assert(x as i4 == 4); - assert(x as i6 == -28 as i6); - assert(x as i8 == 100); - assert(x as i8 == 100); - assert(x as i8 == 100); + let x: i32 = 456; + assert(x as i8 == -56 as i8); + assert(x as i64 == 456); } unconstrained fn mixed_casts() { assert(100 as u32 as i32 as u32 == 100); - assert(13 as u4 as i2 as u32 == 1); - assert(15 as u4 as i2 as u32 == 3); + assert(257 as u8 as u32 == 1); assert(1 as u8 as bool == true); assert(true as i8 == 1); } diff --git a/test_programs/compile_success_empty/brillig_modulo/src/main.nr b/test_programs/compile_success_empty/brillig_modulo/src/main.nr index ed0353b101a..195ed31fb08 100644 --- a/test_programs/compile_success_empty/brillig_modulo/src/main.nr +++ b/test_programs/compile_success_empty/brillig_modulo/src/main.nr @@ -7,9 +7,9 @@ fn main() { assert(signed_modulo(5, 3) == 2); assert(signed_modulo(2, 3) == 2); - let minus_two: i4 = -2; // 14 - let minus_three: i4 = -3; // 13 - let minus_five: i4 = -5; // 11 + let minus_two: i8 = -2; // 254 + let minus_three: i8 = -3; // 253 + let minus_five: i8 = -5; // 251 // (5 / -3) * -3 + 2 = -1 * -3 + 2 = 3 + 2 = 5 assert(signed_modulo(5, minus_three) == 2); // (-5 / 3) * 3 - 2 = -1 * 3 - 2 = -3 - 2 = -5 @@ -22,6 +22,6 @@ unconstrained fn modulo(x: u32, y: u32) -> u32 { x % y } -unconstrained fn signed_modulo(x: i4, y: i4) -> i4 { +unconstrained fn signed_modulo(x: i8, y: i8) -> i8 { x % y } diff --git a/test_programs/execution_success/5_over/src/main.nr b/test_programs/execution_success/5_over/src/main.nr index f24ff06cb2a..313d580a8d1 100644 --- a/test_programs/execution_success/5_over/src/main.nr +++ b/test_programs/execution_success/5_over/src/main.nr @@ -5,6 +5,6 @@ fn main(mut x: u32, y: u32) { x = std::wrapping_mul(x,x); assert(y == x); - let c: u3 = 2; - assert(c > x as u3); + let c: u1 = 0; + assert(x as u1 > c); } diff --git a/test_programs/execution_success/bit_shifts_comptime/src/main.nr b/test_programs/execution_success/bit_shifts_comptime/src/main.nr index 9bb1028173d..9184b5bd5e6 100644 --- a/test_programs/execution_success/bit_shifts_comptime/src/main.nr +++ b/test_programs/execution_success/bit_shifts_comptime/src/main.nr @@ -14,7 +14,7 @@ fn main(x: u64) { //regression for 3481 assert(x << 63 == 0); - assert_eq((1 as u56) << (32 as u56), 0x0100000000); + assert_eq((1 as u64) << (32 as u64), 0x0100000000); } fn regression_2250() { diff --git a/test_programs/execution_success/conditional_regression_underflow/src/main.nr b/test_programs/execution_success/conditional_regression_underflow/src/main.nr index a101af32505..aaf3754a20f 100644 --- a/test_programs/execution_success/conditional_regression_underflow/src/main.nr +++ b/test_programs/execution_success/conditional_regression_underflow/src/main.nr @@ -1,12 +1,12 @@ // Regression test for https://github.com/noir-lang/noir/issues/3493 -fn main(x: u4) { +fn main(x: u8) { if x == 10 { - x + 15; + x + 255; } if x == 9 { - x << 3; + x << 7; } - if x == 8 { + if x == 128 { x * 3; } if x == 7 { diff --git a/test_programs/execution_success/regression/src/main.nr b/test_programs/execution_success/regression/src/main.nr index 08112d4c616..c70e2e75fa8 100644 --- a/test_programs/execution_success/regression/src/main.nr +++ b/test_programs/execution_success/regression/src/main.nr @@ -1,29 +1,49 @@ global NIBBLE_LENGTH: Field = 16; -fn compact_decode(input: [u8; N], length: Field) -> ([u4; NIBBLE_LENGTH], Field) { +struct U4 { + inner: u8, +} + +impl U4 { + fn zero() -> U4 { + U4 { inner: 0 } + } + + fn from_u8(x: u8) -> U4 { + U4 { inner: x % 16 } + } +} + +impl Eq for U4 { + fn eq(self, other: Self) -> bool { + self.inner == other.inner + } +} + +fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Field) { assert(2 * input.len() as u64 <= NIBBLE_LENGTH as u64); assert(length as u64 <= input.len() as u64); - let mut nibble = [0 as u4; NIBBLE_LENGTH]; + let mut nibble = [U4::zero(); NIBBLE_LENGTH]; - let first_nibble = (input[0] >> 4) as u4; - let parity = first_nibble as u1; + let first_nibble = U4::from_u8(input[0] >> 4); + let parity = first_nibble.inner as u1; if parity == 1 { - nibble[0] = (input[0] & 0x0f) as u4; + nibble[0] = U4::from_u8(input[0] & 0x0f); for i in 1..input.len() { if i as u64 < length as u64 { let x = input[i]; - nibble[2*i - 1] = (x >> 4) as u4; - nibble[2*i] = (x & 0x0f) as u4; + nibble[2*i - 1] = U4::from_u8(x >> 4); + nibble[2*i] = U4::from_u8(x & 0x0f); } } } else { for i in 0..2 { if (i as u64) < length as u64 - 1 { let x = input[i + 1]; - nibble[2*i] = (x >> 4) as u4; - nibble[2*i + 1] = (x & 0x0f) as u4; + nibble[2*i] = U4::from_u8(x >> 4); + nibble[2*i + 1] = U4::from_u8(x & 0x0f); } } } @@ -78,7 +98,10 @@ fn main(x: [u8; 5], z: Field) { //Issue 1144 let (nib, len) = compact_decode(x, z); assert(len == 5); - assert([nib[0], nib[1], nib[2], nib[3], nib[4]] == [15, 1, 12, 11, 8]); + assert( + [nib[0], nib[1], nib[2], nib[3], nib[4]] + == [U4::from_u8(15), U4::from_u8(1), U4::from_u8(12), U4::from_u8(11), U4::from_u8(8)] + ); // Issue 1169 let val1 = [ 0xb8, 0x8f, 0x61, 0xe6, 0xfb, 0xda, 0x83, 0xfb, 0xff, 0xfa, 0xbe, 0x36, 0x41, 0x12, 0x13, From 94b60a86159b678d3386e130f5c402a971ed6a27 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 2 Feb 2024 12:18:41 +0000 Subject: [PATCH 2/5] feat!: Restrict bit sizes --- aztec_macros/src/lib.rs | 5 +- .../src/ssa/ssa_gen/context.rs | 4 +- compiler/noirc_frontend/src/ast/mod.rs | 63 +++++++++++++++++-- .../src/hir/type_check/errors.rs | 3 +- .../noirc_frontend/src/hir/type_check/stmt.rs | 1 + compiler/noirc_frontend/src/hir_def/types.rs | 13 ++-- compiler/noirc_frontend/src/lexer/errors.rs | 10 --- compiler/noirc_frontend/src/lexer/lexer.rs | 2 +- compiler/noirc_frontend/src/lexer/token.rs | 8 +-- .../src/monomorphization/ast.rs | 7 ++- .../src/monomorphization/mod.rs | 15 ++--- compiler/noirc_frontend/src/parser/errors.rs | 11 ++-- compiler/noirc_frontend/src/parser/parser.rs | 22 +++---- .../regression_2854/Nargo.toml | 6 -- .../regression_2854/Prover.toml | 1 - .../regression_2854/src/main.nr | 3 - tooling/noirc_abi/src/lib.rs | 2 +- 17 files changed, 104 insertions(+), 72 deletions(-) delete mode 100644 test_programs/execution_success/regression_2854/Nargo.toml delete mode 100644 test_programs/execution_success/regression_2854/Prover.toml delete mode 100644 test_programs/execution_success/regression_2854/src/main.nr diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs index baabd9aa1dc..6186a55a03b 100644 --- a/aztec_macros/src/lib.rs +++ b/aztec_macros/src/lib.rs @@ -721,7 +721,10 @@ fn create_context(ty: &str, params: &[Param]) -> Result, AztecMac add_array_to_hasher( &id, &UnresolvedType { - typ: UnresolvedTypeData::Integer(Signedness::Unsigned, 32), + typ: UnresolvedTypeData::Integer( + Signedness::Unsigned, + noirc_frontend::IntegerBitSize::ThirtyTwo, + ), span: None, }, ) diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index adf68bacba4..08b118dd824 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -219,8 +219,8 @@ impl<'a> FunctionContext<'a> { let element_types = Self::convert_type(element).flatten(); Type::Array(Rc::new(element_types), *len as usize) } - ast::Type::Integer(Signedness::Signed, bits) => Type::signed(*bits), - ast::Type::Integer(Signedness::Unsigned, bits) => Type::unsigned(*bits), + ast::Type::Integer(Signedness::Signed, bits) => Type::signed((*bits).into()), + ast::Type::Integer(Signedness::Unsigned, bits) => Type::unsigned((*bits).into()), ast::Type::Bool => Type::unsigned(1), ast::Type::String(len) => Type::Array(Rc::new(vec![Type::char()]), *len as usize), ast::Type::FmtString(_, _) => { diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index d9af5893024..22b104e48b3 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -28,6 +28,55 @@ use crate::{ }; use iter_extended::vecmap; +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Ord, PartialOrd)] +pub enum IntegerBitSize { + One, + Eight, + ThirtyTwo, + SixtyFour, +} + +impl IntegerBitSize { + pub fn allowed_sizes() -> Vec { + vec![Self::One, Self::Eight, Self::ThirtyTwo, Self::SixtyFour] + } +} + +impl From for u32 { + fn from(size: IntegerBitSize) -> u32 { + use IntegerBitSize::*; + match size { + One => 1, + Eight => 8, + ThirtyTwo => 32, + SixtyFour => 64, + } + } +} + +pub struct InvalidIntegerBitSizeError(pub u32); + +impl TryFrom for IntegerBitSize { + type Error = InvalidIntegerBitSizeError; + + fn try_from(value: u32) -> Result { + use IntegerBitSize::*; + match value { + 1 => Ok(One), + 8 => Ok(Eight), + 32 => Ok(ThirtyTwo), + 64 => Ok(SixtyFour), + _ => Err(InvalidIntegerBitSizeError(value)), + } + } +} + +impl core::fmt::Display for IntegerBitSize { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", u32::from(*self)) + } +} + /// The parser parses types as 'UnresolvedType's which /// require name resolution to resolve any type names used /// for structs within, but are otherwise identical to Types. @@ -35,7 +84,7 @@ use iter_extended::vecmap; pub enum UnresolvedTypeData { FieldElement, Array(Option, Box), // [4]Witness = Array(4, Witness) - Integer(Signedness, u32), // u32 = Integer(unsigned, 32) + Integer(Signedness, IntegerBitSize), // u32 = Integer(unsigned, ThirtyTwo) Bool, Expression(UnresolvedTypeExpression), String(Option), @@ -189,11 +238,17 @@ impl UnresolvedType { } impl UnresolvedTypeData { - pub fn from_int_token(token: IntType) -> UnresolvedTypeData { + pub fn from_int_token( + token: IntType, + ) -> Result { use {IntType::*, UnresolvedTypeData::Integer}; match token { - Signed(num_bits) => Integer(Signedness::Signed, num_bits), - Unsigned(num_bits) => Integer(Signedness::Unsigned, num_bits), + Signed(num_bits) => { + Ok(Integer(Signedness::Signed, IntegerBitSize::try_from(num_bits)?)) + } + Unsigned(num_bits) => { + Ok(Integer(Signedness::Unsigned, IntegerBitSize::try_from(num_bits)?)) + } } } diff --git a/compiler/noirc_frontend/src/hir/type_check/errors.rs b/compiler/noirc_frontend/src/hir/type_check/errors.rs index 267dbd6b5be..c1e5ead0f12 100644 --- a/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -8,6 +8,7 @@ use crate::hir_def::expr::HirBinaryOp; use crate::hir_def::types::Type; use crate::BinaryOpKind; use crate::FunctionReturnType; +use crate::IntegerBitSize; use crate::Signedness; #[derive(Error, Debug, Clone, PartialEq, Eq)] @@ -67,7 +68,7 @@ pub enum TypeCheckError { #[error("Integers must have the same signedness LHS is {sign_x:?}, RHS is {sign_y:?}")] IntegerSignedness { sign_x: Signedness, sign_y: Signedness, span: Span }, #[error("Integers must have the same bit width LHS is {bit_width_x}, RHS is {bit_width_y}")] - IntegerBitWidth { bit_width_x: u32, bit_width_y: u32, span: Span }, + IntegerBitWidth { bit_width_x: IntegerBitSize, bit_width_y: IntegerBitSize, span: Span }, #[error("{kind} cannot be used in an infix operation")] InvalidInfixOp { kind: &'static str, span: Span }, #[error("{kind} cannot be used in a unary operation")] diff --git a/compiler/noirc_frontend/src/hir/type_check/stmt.rs b/compiler/noirc_frontend/src/hir/type_check/stmt.rs index a38a16a6580..3b0e7ff16b3 100644 --- a/compiler/noirc_frontend/src/hir/type_check/stmt.rs +++ b/compiler/noirc_frontend/src/hir/type_check/stmt.rs @@ -350,6 +350,7 @@ impl<'interner> TypeChecker<'interner> { HirExpression::Literal(HirLiteral::Integer(value, false)) => { let v = value.to_u128(); if let Type::Integer(_, bit_count) = annotated_type { + let bit_count: u32 = (*bit_count).into(); let max = 1 << bit_count; if v >= max { self.errors.push(TypeCheckError::OverflowingAssignment { diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 0ba4cb2da65..ced99bd35ec 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -8,6 +8,7 @@ use std::{ use crate::{ hir::type_check::TypeCheckError, node_interner::{ExprId, NodeInterner, TraitId, TypeAliasId}, + IntegerBitSize, }; use iter_extended::vecmap; use noirc_errors::{Location, Span}; @@ -27,8 +28,8 @@ pub enum Type { Array(Box, Box), /// A primitive integer type with the given sign and bit count. - /// E.g. `u32` would be `Integer(Unsigned, 32)` - Integer(Signedness, u32), + /// E.g. `u32` would be `Integer(Unsigned, ThirtyTwo)` + Integer(Signedness, IntegerBitSize), /// The primitive `bool` type. Bool, @@ -538,7 +539,7 @@ impl Type { } pub fn default_range_loop_type() -> Type { - Type::Integer(Signedness::Unsigned, 64) + Type::Integer(Signedness::Unsigned, IntegerBitSize::SixtyFour) } pub fn type_variable(id: TypeVariableId) -> Type { @@ -1622,8 +1623,10 @@ impl From<&Type> for PrintableType { PrintableType::Array { length, typ: Box::new(typ.into()) } } Type::Integer(sign, bit_width) => match sign { - Signedness::Unsigned => PrintableType::UnsignedInteger { width: *bit_width }, - Signedness::Signed => PrintableType::SignedInteger { width: *bit_width }, + Signedness::Unsigned => { + PrintableType::UnsignedInteger { width: (*bit_width).into() } + } + Signedness::Signed => PrintableType::SignedInteger { width: (*bit_width).into() }, }, Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => { match &*binding.borrow() { diff --git a/compiler/noirc_frontend/src/lexer/errors.rs b/compiler/noirc_frontend/src/lexer/errors.rs index a2a4056f1d0..35a07c11e0a 100644 --- a/compiler/noirc_frontend/src/lexer/errors.rs +++ b/compiler/noirc_frontend/src/lexer/errors.rs @@ -17,8 +17,6 @@ pub enum LexerErrorKind { InvalidIntegerLiteral { span: Span, found: String }, #[error("{:?} is not a valid attribute", found)] MalformedFuncAttribute { span: Span, found: String }, - #[error("Integer type is larger than the maximum supported size of u127")] - TooManyBits { span: Span, max: u32, got: u32 }, #[error("Logical and used instead of bitwise and")] LogicalAnd { span: Span }, #[error("Unterminated block comment")] @@ -45,7 +43,6 @@ impl LexerErrorKind { LexerErrorKind::NotADoubleChar { span, .. } => *span, LexerErrorKind::InvalidIntegerLiteral { span, .. } => *span, LexerErrorKind::MalformedFuncAttribute { span, .. } => *span, - LexerErrorKind::TooManyBits { span, .. } => *span, LexerErrorKind::LogicalAnd { span } => *span, LexerErrorKind::UnterminatedBlockComment { span } => *span, LexerErrorKind::UnterminatedStringLiteral { span } => *span, @@ -85,13 +82,6 @@ impl LexerErrorKind { format!(" {found} is not a valid attribute"), *span, ), - LexerErrorKind::TooManyBits { span, max, got } => ( - "Integer literal too large".to_string(), - format!( - "The maximum number of bits needed to represent a field is {max}, This integer type needs {got} bits" - ), - *span, - ), LexerErrorKind::LogicalAnd { span } => ( "Noir has no logical-and (&&) operator since short-circuiting is much less efficient when compiling to circuits".to_string(), "Try `&` instead, or use `if` only if you require short-circuiting".to_string(), diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index fd8168e36c6..cf66ece0c30 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -307,7 +307,7 @@ impl<'a> Lexer<'a> { // Check if word an int type // if no error occurred, then it is either a valid integer type or it is not an int type - let parsed_token = IntType::lookup_int_type(&word, Span::inclusive(start, end))?; + let parsed_token = IntType::lookup_int_type(&word)?; // Check if it is an int type if let Some(int_type_token) = parsed_token { diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 835a0baae3f..6895a147d51 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -306,7 +306,7 @@ impl IntType { // XXX: Result // Is not the best API. We could split this into two functions. One that checks if the the // word is a integer, which only returns an Option - pub(crate) fn lookup_int_type(word: &str, span: Span) -> Result, LexerErrorKind> { + pub(crate) fn lookup_int_type(word: &str) -> Result, LexerErrorKind> { // Check if the first string is a 'u' or 'i' let is_signed = if word.starts_with('i') { @@ -324,12 +324,6 @@ impl IntType { Err(_) => return Ok(None), }; - let max_bits = FieldElement::max_num_bits() / 2; - - if str_as_u32 > max_bits { - return Err(LexerErrorKind::TooManyBits { span, max: max_bits, got: str_as_u32 }); - } - if is_signed { Ok(Some(Token::IntType(IntType::Signed(str_as_u32)))) } else { diff --git a/compiler/noirc_frontend/src/monomorphization/ast.rs b/compiler/noirc_frontend/src/monomorphization/ast.rs index 5172eabde46..58a59d8e9b2 100644 --- a/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -3,7 +3,8 @@ use iter_extended::vecmap; use noirc_errors::Location; use crate::{ - hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, Signedness, Visibility, + hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, IntegerBitSize, Signedness, + Visibility, }; /// The monomorphized AST is expression-based, all statements are also @@ -214,8 +215,8 @@ pub struct Function { #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum Type { Field, - Array(/*len:*/ u64, Box), // Array(4, Field) = [Field; 4] - Integer(Signedness, /*bits:*/ u32), // u32 = Integer(unsigned, 32) + Array(/*len:*/ u64, Box), // Array(4, Field) = [Field; 4] + Integer(Signedness, /*bits:*/ IntegerBitSize), // u32 = Integer(unsigned, ThirtyTwo) Bool, String(/*len:*/ u64), // String(4) = str[4] FmtString(/*len:*/ u64, Box), diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 7e06b94ca5a..530f83b96c2 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -26,8 +26,8 @@ use crate::{ }, node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKind, TraitMethodId}, token::FunctionAttribute, - ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, TypeVariable, - TypeVariableKind, UnaryOp, Visibility, + ContractFunctionType, FunctionKind, IntegerBitSize, Type, TypeBinding, TypeBindings, + TypeVariable, TypeVariableKind, UnaryOp, Visibility, }; use self::ast::{Definition, FuncId, Function, LocalId, Program}; @@ -331,6 +331,7 @@ impl<'interner> Monomorphizer<'interner> { match typ { ast::Type::Field => Literal(Integer(-value, typ, location)), ast::Type::Integer(_, bit_size) => { + let bit_size: u32 = bit_size.into(); let base = 1_u128 << bit_size; Literal(Integer(FieldElement::from(base) - value, typ, location)) } @@ -1079,19 +1080,19 @@ impl<'interner> Monomorphizer<'interner> { } "modulus_le_bits" => { let bits = FieldElement::modulus().to_radix_le(2); - Some(self.modulus_array_literal(bits, 1, location)) + Some(self.modulus_array_literal(bits, IntegerBitSize::One, location)) } "modulus_be_bits" => { let bits = FieldElement::modulus().to_radix_be(2); - Some(self.modulus_array_literal(bits, 1, location)) + Some(self.modulus_array_literal(bits, IntegerBitSize::One, location)) } "modulus_be_bytes" => { let bytes = FieldElement::modulus().to_bytes_be(); - Some(self.modulus_array_literal(bytes, 8, location)) + Some(self.modulus_array_literal(bytes, IntegerBitSize::Eight, location)) } "modulus_le_bytes" => { let bytes = FieldElement::modulus().to_bytes_le(); - Some(self.modulus_array_literal(bytes, 8, location)) + Some(self.modulus_array_literal(bytes, IntegerBitSize::Eight, location)) } _ => None, }; @@ -1103,7 +1104,7 @@ impl<'interner> Monomorphizer<'interner> { fn modulus_array_literal( &self, bytes: Vec, - arr_elem_bits: u32, + arr_elem_bits: IntegerBitSize, location: Location, ) -> ast::Expression { use ast::*; diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index 9158c68db72..a3435ee763e 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -1,6 +1,7 @@ use crate::lexer::errors::LexerErrorKind; use crate::lexer::token::Token; use crate::Expression; +use crate::IntegerBitSize; use small_ord_set::SmallOrdSet; use thiserror::Error; @@ -41,7 +42,7 @@ pub enum ParserErrorReason { #[error("Assert statements can only accept string literals")] AssertMessageNotString, #[error("Integer bit size {0} won't be supported")] - DeprecatedBitSize(u32), + InvalidBitSize(u32), #[error("{0}")] Lexer(LexerErrorKind), } @@ -132,8 +133,6 @@ impl std::fmt::Display for ParserError { } } -pub(crate) static ALLOWED_INTEGER_BIT_SIZES: &[u32] = &[1, 8, 32, 64]; - impl From for Diagnostic { fn from(error: ParserError) -> Diagnostic { match error.reason { @@ -149,9 +148,9 @@ impl From for Diagnostic { "The 'comptime' keyword has been deprecated. It can be removed without affecting your program".into(), error.span, ), - ParserErrorReason::DeprecatedBitSize(bit_size) => Diagnostic::simple_warning( - format!("Use of deprecated bit size {}", bit_size), - format!("Bit sizes for integers will be restricted to {}", ALLOWED_INTEGER_BIT_SIZES.iter().map(|n| n.to_string()).collect::>().join(", ")), + ParserErrorReason::InvalidBitSize(bit_size) => Diagnostic::simple_error( + format!("Use of invalid bit size {}", bit_size), + format!("Allowed bit sizes for integers are {}", IntegerBitSize::allowed_sizes().iter().map(|n| n.to_string()).collect::>().join(", ")), error.span, ), ParserErrorReason::ExperimentalFeature(_) => Diagnostic::simple_warning( diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 1f41a29dd4f..9d030181a9f 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -23,7 +23,6 @@ //! prevent other parsers from being tried afterward since there is no longer an error. Thus, they should //! be limited to cases like the above `fn` example where it is clear we shouldn't back out of the //! current parser to try alternative parsers in a `choice` expression. -use super::errors::ALLOWED_INTEGER_BIT_SIZES; use super::{ foldl_with_span, labels::ParsingRuleLabel, parameter_name_recovery, parameter_recovery, parenthesized, then_commit, then_commit_ignore, top_level_statement_recovery, ExprParser, @@ -36,7 +35,7 @@ use crate::ast::{ }; use crate::lexer::Lexer; use crate::parser::{force, ignore_then_commit, statement_recovery}; -use crate::token::{Attribute, Attributes, IntType, Keyword, SecondaryAttribute, Token, TokenKind}; +use crate::token::{Attribute, Attributes, Keyword, SecondaryAttribute, Token, TokenKind}; use crate::{ BinaryOp, BinaryOpKind, BlockExpression, ConstrainKind, ConstrainStatement, Distinctness, ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, FunctionVisibility, Ident, @@ -1093,19 +1092,14 @@ fn int_type() -> impl NoirParser { Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) } })) - .validate(|int_type, span, emit| { - let bit_size = match int_type.1 { - IntType::Signed(bit_size) | IntType::Unsigned(bit_size) => bit_size, - }; - if !ALLOWED_INTEGER_BIT_SIZES.contains(&bit_size) { - emit(ParserError::with_reason( - ParserErrorReason::DeprecatedBitSize(bit_size), - span, - )); - } - int_type + .validate(|(_, token), span, emit| { + UnresolvedTypeData::from_int_token(token) + .map(|data| data.with_span(span)) + .unwrap_or_else(|err| { + emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); + UnresolvedType::error(span) + }) }) - .map_with_span(|(_, token), span| UnresolvedTypeData::from_int_token(token).with_span(span)) } fn named_type(type_parser: impl NoirParser) -> impl NoirParser { diff --git a/test_programs/execution_success/regression_2854/Nargo.toml b/test_programs/execution_success/regression_2854/Nargo.toml deleted file mode 100644 index fb2b3c42fdd..00000000000 --- a/test_programs/execution_success/regression_2854/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "regression_2854" -type = "bin" -authors = [""] - -[dependencies] diff --git a/test_programs/execution_success/regression_2854/Prover.toml b/test_programs/execution_success/regression_2854/Prover.toml deleted file mode 100644 index 07890234a19..00000000000 --- a/test_programs/execution_success/regression_2854/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = "3" diff --git a/test_programs/execution_success/regression_2854/src/main.nr b/test_programs/execution_success/regression_2854/src/main.nr deleted file mode 100644 index eccff8225b6..00000000000 --- a/test_programs/execution_success/regression_2854/src/main.nr +++ /dev/null @@ -1,3 +0,0 @@ -fn main(x: Field) -> pub i127 { - x as i127 -} diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index 1fc257c1676..2560e46b01d 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -142,7 +142,7 @@ impl AbiType { Signedness::Signed => Sign::Signed, }; - Self::Integer { sign, width: *bit_width } + Self::Integer { sign, width: (*bit_width).into() } } Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => { match &*binding.borrow() { From d1513973388bf7d73a582e2b735ed87a061e7739 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Tue, 13 Feb 2024 11:24:31 +0000 Subject: [PATCH 3/5] docs: clarify the restricted sizes of integers --- cspell.json | 1 + docs/docs/noir/concepts/data_types/integers.md | 9 +-------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/cspell.json b/cspell.json index 19e9a175ce0..2acca0633d3 100644 --- a/cspell.json +++ b/cspell.json @@ -106,6 +106,7 @@ "lvalue", "Maddiaa", "mathbb", + "memfs", "merkle", "metas", "minreq", diff --git a/docs/docs/noir/concepts/data_types/integers.md b/docs/docs/noir/concepts/data_types/integers.md index 30135d76e4a..4d58d96fed5 100644 --- a/docs/docs/noir/concepts/data_types/integers.md +++ b/docs/docs/noir/concepts/data_types/integers.md @@ -5,7 +5,7 @@ keywords: [noir, integer types, methods, examples, arithmetic] sidebar_position: 1 --- -An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. +An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. :::info @@ -45,13 +45,6 @@ fn main() { The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). -:::tip - -If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. - -::: - - ## 128 bits Unsigned Integers The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: From ef101426034dec81b27392077f4d5e4f23682ead Mon Sep 17 00:00:00 2001 From: sirasistant Date: Tue, 13 Feb 2024 11:34:51 +0000 Subject: [PATCH 4/5] test: added e2e test for restricted bit size --- .../compile_failure/restricted_bit_sizes/Nargo.toml | 5 +++++ .../compile_failure/restricted_bit_sizes/src/main.nr | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 test_programs/compile_failure/restricted_bit_sizes/Nargo.toml create mode 100644 test_programs/compile_failure/restricted_bit_sizes/src/main.nr diff --git a/test_programs/compile_failure/restricted_bit_sizes/Nargo.toml b/test_programs/compile_failure/restricted_bit_sizes/Nargo.toml new file mode 100644 index 00000000000..36f8253e8e7 --- /dev/null +++ b/test_programs/compile_failure/restricted_bit_sizes/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "restricted_bit_sizes" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/restricted_bit_sizes/src/main.nr b/test_programs/compile_failure/restricted_bit_sizes/src/main.nr new file mode 100644 index 00000000000..01e72bfcfd7 --- /dev/null +++ b/test_programs/compile_failure/restricted_bit_sizes/src/main.nr @@ -0,0 +1,5 @@ +use dep::std::assert_constant; + +fn main() -> pub u63 { + 5 +} From 2604d2a9fc1a2a2dc9832550e138506b74ed8ba1 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Tue, 13 Feb 2024 11:41:00 +0000 Subject: [PATCH 5/5] test: remove u4 from test --- .../compile_failure/integer_literal_overflow/src/main.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_programs/compile_failure/integer_literal_overflow/src/main.nr b/test_programs/compile_failure/integer_literal_overflow/src/main.nr index d89505c0085..e4d21b5c3b9 100644 --- a/test_programs/compile_failure/integer_literal_overflow/src/main.nr +++ b/test_programs/compile_failure/integer_literal_overflow/src/main.nr @@ -2,4 +2,4 @@ fn main() { foo(1234) } -fn foo(_x: u4) {} +fn foo(_x: u8) {}