From 3b699d6b92b51efbd040e1ca686c9cea94cd006b Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 2 Feb 2024 11:09:54 +0000 Subject: [PATCH] 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,