diff --git a/.aztec-sync-commit b/.aztec-sync-commit index f60456adac1..e485a975265 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -bcec12dbf79b658406dc21083f8fdeef8962085e +7fb2a454531db8cef757b5ec2028d97e823bef5f diff --git a/Cargo.lock b/Cargo.lock index 9a657dcf9d0..e8f06054cf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -441,13 +441,15 @@ name = "aztec_macros" version = "0.34.0" dependencies = [ "acvm", + "bn254_blackbox_solver", "convert_case 0.6.0", + "hex", "im", "iter-extended", + "itertools", "noirc_errors", "noirc_frontend", "regex", - "tiny-keccak", ] [[package]] @@ -1124,12 +1126,6 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - [[package]] name = "crypto-bigint" version = "0.4.9" @@ -4543,15 +4539,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinytemplate" version = "1.2.1" diff --git a/acvm-repo/acir/codegen/acir.cpp b/acvm-repo/acir/codegen/acir.cpp index a789a0f0c47..875f076a911 100644 --- a/acvm-repo/acir/codegen/acir.cpp +++ b/acvm-repo/acir/codegen/acir.cpp @@ -462,7 +462,7 @@ namespace Program { struct ToRadix { Program::MemoryAddress input; - uint32_t radix; + Program::MemoryAddress radix; Program::HeapArray output; bool output_bits; diff --git a/acvm-repo/bn254_blackbox_solver/src/lib.rs b/acvm-repo/bn254_blackbox_solver/src/lib.rs index 43ee6a9ddd2..952c4498d84 100644 --- a/acvm-repo/bn254_blackbox_solver/src/lib.rs +++ b/acvm-repo/bn254_blackbox_solver/src/lib.rs @@ -13,7 +13,10 @@ mod schnorr; use ark_ec::AffineRepr; pub use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul}; pub use generator::generators::derive_generators; -pub use poseidon2::{field_from_hex, poseidon2_permutation, Poseidon2Config, POSEIDON2_CONFIG}; +pub use poseidon2::{ + field_from_hex, poseidon2_permutation, poseidon_hash, Poseidon2Config, Poseidon2Sponge, + POSEIDON2_CONFIG, +}; // Temporary hack, this ensure that we always use a bn254 field here // without polluting the feature flags of the `acir_field` crate. diff --git a/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs b/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs index dd3e8b725c2..64823e37029 100644 --- a/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs +++ b/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs @@ -543,6 +543,75 @@ impl<'a> Poseidon2<'a> { } } +/// Performs a poseidon hash with a sponge construction equivalent to the one in poseidon2.nr +pub fn poseidon_hash(inputs: &[FieldElement]) -> Result { + let two_pow_64 = 18446744073709551616_u128.into(); + let iv = FieldElement::from(inputs.len()) * two_pow_64; + let mut sponge = Poseidon2Sponge::new(iv, 3); + for input in inputs.iter() { + sponge.absorb(*input)?; + } + sponge.squeeze() +} + +pub struct Poseidon2Sponge<'a> { + rate: usize, + poseidon: Poseidon2<'a>, + squeezed: bool, + cache: Vec, + state: Vec, +} + +impl<'a> Poseidon2Sponge<'a> { + pub fn new(iv: FieldElement, rate: usize) -> Poseidon2Sponge<'a> { + let mut result = Poseidon2Sponge { + cache: Vec::with_capacity(rate), + state: vec![FieldElement::zero(); rate + 1], + squeezed: false, + rate, + poseidon: Poseidon2::new(), + }; + result.state[rate] = iv; + result + } + + fn perform_duplex(&mut self) -> Result<(), BlackBoxResolutionError> { + // zero-pad the cache + for _ in self.cache.len()..self.rate { + self.cache.push(FieldElement::zero()); + } + // add the cache into sponge state + for i in 0..self.rate { + self.state[i] += self.cache[i]; + } + self.state = self.poseidon.permutation(&self.state, 4)?; + Ok(()) + } + + pub fn absorb(&mut self, input: FieldElement) -> Result<(), BlackBoxResolutionError> { + assert!(!self.squeezed); + if self.cache.len() == self.rate { + // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache + self.perform_duplex()?; + self.cache = vec![input]; + } else { + // If we're absorbing, and the cache is not full, add the input into the cache + self.cache.push(input); + } + Ok(()) + } + + pub fn squeeze(&mut self) -> Result { + assert!(!self.squeezed); + // If we're in absorb mode, apply sponge permutation to compress the cache. + self.perform_duplex()?; + self.squeezed = true; + + // Pop one item off the top of the permutation and return it. + Ok(self.state[0]) + } +} + #[cfg(test)] mod test { use acir::AcirField; @@ -562,4 +631,19 @@ mod test { ]; assert_eq!(result, expected_result); } + + #[test] + fn hash_smoke_test() { + let fields = [ + FieldElement::from(1u128), + FieldElement::from(2u128), + FieldElement::from(3u128), + FieldElement::from(4u128), + ]; + let result = super::poseidon_hash(&fields).expect("should hash successfully"); + assert_eq!( + result, + field_from_hex("130bf204a32cac1f0ace56c78b731aa3809f06df2731ebcf6b3464a15788b1b9"), + ); + } } diff --git a/acvm-repo/brillig/src/black_box.rs b/acvm-repo/brillig/src/black_box.rs index c3240c6ff1e..7dccfbf677f 100644 --- a/acvm-repo/brillig/src/black_box.rs +++ b/acvm-repo/brillig/src/black_box.rs @@ -130,7 +130,7 @@ pub enum BlackBoxOp { }, ToRadix { input: MemoryAddress, - radix: u32, + radix: MemoryAddress, output: HeapArray, output_bits: bool, }, diff --git a/acvm-repo/brillig_vm/src/black_box.rs b/acvm-repo/brillig_vm/src/black_box.rs index 3f1a44b921b..8d1bf3ec2ea 100644 --- a/acvm-repo/brillig_vm/src/black_box.rs +++ b/acvm-repo/brillig_vm/src/black_box.rs @@ -369,9 +369,13 @@ pub(crate) fn evaluate_black_box } BlackBoxOp::ToRadix { input, radix, output, output_bits } => { let input: F = *memory.read(*input).extract_field().expect("ToRadix input not a field"); + let radix = memory + .read(*radix) + .expect_integer_with_bit_size(IntegerBitSize::U32) + .expect("ToRadix opcode's radix bit size does not match expected bit size 32"); let mut input = BigUint::from_bytes_be(&input.to_be_bytes()); - let radix = BigUint::from(*radix); + let radix = BigUint::from_bytes_be(&radix.to_be_bytes()); let mut limbs: Vec> = Vec::with_capacity(output.size); diff --git a/aztec_macros/Cargo.toml b/aztec_macros/Cargo.toml index 258379cd7b8..e7bee99b74e 100644 --- a/aztec_macros/Cargo.toml +++ b/aztec_macros/Cargo.toml @@ -17,7 +17,9 @@ acvm.workspace = true noirc_frontend.workspace = true noirc_errors.workspace = true iter-extended.workspace = true +bn254_blackbox_solver.workspace = true convert_case = "0.6.0" im.workspace = true regex = "1.10" -tiny-keccak = { version = "2.0.0", features = ["keccak"] } +itertools = "^0.10" +hex.workspace = true diff --git a/aztec_macros/src/transforms/contract_interface.rs b/aztec_macros/src/transforms/contract_interface.rs index e2de30d6d93..522489daa1b 100644 --- a/aztec_macros/src/transforms/contract_interface.rs +++ b/aztec_macros/src/transforms/contract_interface.rs @@ -1,5 +1,6 @@ use acvm::acir::AcirField; +use bn254_blackbox_solver::poseidon_hash; use noirc_errors::Location; use noirc_frontend::ast::{Documented, Ident, NoirFunction, UnresolvedTypeData}; use noirc_frontend::{ @@ -9,7 +10,7 @@ use noirc_frontend::{ Type, }; -use tiny_keccak::{Hasher, Keccak}; +use itertools::Itertools; use crate::utils::parse_utils::parse_program; use crate::utils::{ @@ -251,7 +252,7 @@ pub fn generate_contract_interface( module_name, stubs.iter().map(|(src, _)| src.to_owned()).collect::>().join("\n"), if has_storage_layout { storage_layout_getter.clone() } else { "".to_string() }, - if has_storage_layout { format!("#[contract_library_method]\n{}", storage_layout_getter) } else { "".to_string() } + if has_storage_layout { format!("#[contract_library_method]\n{}", storage_layout_getter) } else { "".to_string() } ); let (contract_interface_ast, errors) = parse_program(&contract_interface, empty_spans); @@ -296,14 +297,8 @@ fn compute_fn_signature_hash(fn_name: &str, parameters: &[Type]) -> u32 { fn_name, parameters.iter().map(signature_of_type).collect::>().join(",") ); - let mut keccak = Keccak::v256(); - let mut result = [0u8; 32]; - keccak.update(signature.as_bytes()); - keccak.finalize(&mut result); - // Take the first 4 bytes of the hash and convert them to an integer - // If you change the following value you have to change NUM_BYTES_PER_NOTE_TYPE_ID in l1_note_payload.ts as well - let num_bytes_per_note_type_id = 4; - u32::from_be_bytes(result[0..num_bytes_per_note_type_id].try_into().unwrap()) + + hash_to_selector(&signature) } // Updates the function signatures in the contract interface with the actual ones, replacing the placeholder. @@ -429,3 +424,45 @@ pub fn update_fn_signatures_in_contract_interface( } Ok(()) } + +fn poseidon2_hash_bytes(inputs: Vec) -> FieldElement { + let fields: Vec<_> = inputs + .into_iter() + .chunks(31) + .into_iter() + .map(|bytes_chunk| { + let mut chunk_as_vec: Vec = bytes_chunk.collect(); + chunk_as_vec.extend(std::iter::repeat(0).take(32 - chunk_as_vec.len())); + // Build a little endian field element + chunk_as_vec.reverse(); + FieldElement::from_be_bytes_reduce(&chunk_as_vec) + }) + .collect(); + + poseidon_hash(&fields).expect("Poseidon hash failed") +} + +pub(crate) fn hash_to_selector(inputs: &str) -> u32 { + let hash = poseidon2_hash_bytes(inputs.as_bytes().to_vec()).to_be_bytes(); + // Take the last 4 bytes of the hash and convert them to an integer + // If you change the following value you have to change NUM_BYTES_PER_NOTE_TYPE_ID in l1_note_payload.ts as well + let num_bytes_per_note_type_id = 4; + u32::from_be_bytes(hash[(32 - num_bytes_per_note_type_id)..32].try_into().unwrap()) +} + +#[cfg(test)] +mod test { + use crate::transforms::contract_interface::hash_to_selector; + + #[test] + fn test_selector_is_valid() { + let selector = hash_to_selector("IS_VALID()"); + assert_eq!(hex::encode(&selector.to_be_bytes()), "73cdda47"); + } + + #[test] + fn test_long_selector() { + let selector = hash_to_selector("foo_and_bar_and_baz_and_foo_bar_baz_and_bar_foo"); + assert_eq!(hex::encode(&selector.to_be_bytes()), "7590a997"); + } +} diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs index 8587e08892b..9ca260d1b95 100644 --- a/aztec_macros/src/transforms/note_interface.rs +++ b/aztec_macros/src/transforms/note_interface.rs @@ -12,8 +12,6 @@ use noirc_frontend::{ use acvm::AcirField; use regex::Regex; -// TODO(#7165): nuke the following dependency from here and Cargo.toml -use tiny_keccak::{Hasher, Keccak}; use crate::utils::parse_utils::parse_program; use crate::{ @@ -28,6 +26,8 @@ use crate::{ }, }; +use super::contract_interface::hash_to_selector; + // Automatic implementation of most of the methods in the NoteInterface trait, guiding the user with meaningful error messages in case some // methods must be implemented manually. pub fn generate_note_interface_impl( @@ -751,14 +751,7 @@ fn generate_note_deserialize_content_source( // Utility function to generate the note type id as a Field fn compute_note_type_id(note_type: &str) -> u32 { // TODO(#4519) Improve automatic note id generation and assignment - let mut keccak = Keccak::v256(); - let mut result = [0u8; 32]; - keccak.update(note_type.as_bytes()); - keccak.finalize(&mut result); - // Take the first 4 bytes of the hash and convert them to an integer - // If you change the following value you have to change NUM_BYTES_PER_NOTE_TYPE_ID in l1_note_payload.ts as well - let num_bytes_per_note_type_id = 4; - u32::from_be_bytes(result[0..num_bytes_per_note_type_id].try_into().unwrap()) + hash_to_selector(note_type) } pub fn inject_note_exports( diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs index d92412677ca..c9c31267d7b 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs @@ -78,9 +78,11 @@ impl BrilligContext< let heap_array = self.codegen_brillig_array_to_heap_array(target_array); + let radix_var = self.make_constant_instruction(F::from(radix as u128), 32); + self.black_box_op_instruction(BlackBoxOp::ToRadix { input: source_field.address, - radix, + radix: radix_var.address, output: heap_array, output_bits, }); @@ -91,5 +93,6 @@ impl BrilligContext< self.deallocate_single_addr(items_len); } self.deallocate_register(heap_array.pointer); + self.deallocate_register(radix_var.address); } } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs index ea8969eddf3..0199d9537a6 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs @@ -9,7 +9,7 @@ use super::{ brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, debug_show::DebugToString, registers::RegisterAllocator, - BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }; impl BrilligContext { @@ -20,9 +20,12 @@ impl BrilligContext< pointer_register: MemoryAddress, size: usize, ) { - let size_register = self.make_usize_constant_instruction(size.into()); - self.codegen_allocate_mem(pointer_register, size_register.address); - self.deallocate_single_addr(size_register); + self.load_free_memory_pointer_instruction(pointer_register); + self.codegen_usize_op_in_place( + ReservedRegisters::free_memory_pointer(), + BrilligBinaryOp::Add, + size, + ); } /// Allocates an array of size contained in size_register and stores the diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index 595ca5dedc0..04cd54ca78a 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -786,7 +786,7 @@ fn to_le_radix( }; // Decompose the integer into its radix digits in little endian form. - let decomposed_integer = compute_to_radix(value, radix); + let decomposed_integer = compute_to_radix_le(value, radix); let decomposed_integer = vecmap(0..limb_count as usize, |i| match decomposed_integer.get(i) { Some(digit) => Value::U8(*digit), None => Value::U8(0), @@ -797,7 +797,7 @@ fn to_le_radix( )) } -fn compute_to_radix(field: FieldElement, radix: u32) -> Vec { +fn compute_to_radix_le(field: FieldElement, radix: u32) -> Vec { let bit_size = u32::BITS - (radix - 1).leading_zeros(); let radix_big = BigUint::from(radix); assert_eq!(BigUint::from(2u128).pow(bit_size), radix_big, "ICE: Radix must be a power of 2"); diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index e21db0790d7..22de18b6461 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -131,41 +131,41 @@ fn check_trait_implemented_for_all_t() { trait Default { fn default() -> Self; } - + trait Eq { fn eq(self, other: Self) -> bool; } - + trait IsDefault { fn is_default(self) -> bool; } - + impl IsDefault for T where T: Default + Eq { fn is_default(self) -> bool { self.eq(T::default()) } } - + struct Foo { a: u64, } - + impl Eq for Foo { - fn eq(self, other: Foo) -> bool { self.a == other.a } + fn eq(self, other: Foo) -> bool { self.a == other.a } } - + impl Default for u64 { fn default() -> Self { 0 } } - + impl Default for Foo { fn default() -> Self { Foo { a: Default::default() } } } - + fn main(a: Foo) -> pub bool { a.is_default() }"; @@ -178,12 +178,12 @@ fn check_trait_implementation_duplicate_method() { trait Default { fn default(x: Field, y: Field) -> Field; } - + struct Foo { bar: Field, array: [Field; 2], } - + impl Default for Foo { // Duplicate trait methods should not compile fn default(x: Field, y: Field) -> Field { @@ -194,7 +194,7 @@ fn check_trait_implementation_duplicate_method() { x + 2 * y } } - + fn main() {}"; let errors = get_program_errors(src); @@ -225,16 +225,16 @@ fn check_trait_wrong_method_return_type() { trait Default { fn default() -> Self; } - + struct Foo { } - + impl Default for Foo { fn default() -> Field { 0 } } - + fn main() { } "; @@ -265,18 +265,18 @@ fn check_trait_wrong_method_return_type2() { trait Default { fn default(x: Field, y: Field) -> Self; } - + struct Foo { bar: Field, array: [Field; 2], } - + impl Default for Foo { fn default(x: Field, _y: Field) -> Field { x } } - + fn main() { }"; let errors = get_program_errors(src); @@ -305,22 +305,22 @@ fn check_trait_missing_implementation() { let src = " trait Default { fn default(x: Field, y: Field) -> Self; - + fn method2(x: Field) -> Field; - + } - + struct Foo { bar: Field, array: [Field; 2], } - + impl Default for Foo { fn default(x: Field, y: Field) -> Self { Self { bar: x, array: [x,y] } } } - + fn main() { } "; @@ -352,17 +352,17 @@ fn check_trait_not_in_scope() { bar: Field, array: [Field; 2], } - + // Default trait does not exist impl Default for Foo { fn default(x: Field, y: Field) -> Self { Self { bar: x, array: [x,y] } } } - + fn main() { } - + "; let errors = get_program_errors(src); assert!(!has_parser_error(&errors)); @@ -386,19 +386,19 @@ fn check_trait_wrong_method_name() { let src = " trait Default { } - + struct Foo { bar: Field, array: [Field; 2], } - + // wrong trait name method should not compile impl Default for Foo { fn does_not_exist(x: Field, y: Field) -> Self { Self { bar: x, array: [x,y] } } } - + fn main() { }"; let compilation_errors = get_program_errors(src); @@ -431,17 +431,17 @@ fn check_trait_wrong_parameter() { trait Default { fn default(x: Field) -> Self; } - + struct Foo { bar: u32, } - + impl Default for Foo { fn default(x: u32) -> Self { Foo {bar: x} } } - + fn main() { } "; @@ -474,18 +474,18 @@ fn check_trait_wrong_parameter2() { trait Default { fn default(x: Field, y: Field) -> Self; } - + struct Foo { bar: Field, array: [Field; 2], } - + impl Default for Foo { fn default(x: Field, y: Foo) -> Self { Self { bar: x, array: [x, y.bar] } } } - + fn main() { }"; @@ -518,7 +518,7 @@ fn check_trait_wrong_parameter_type() { pub trait Default { fn default(x: Field, y: NotAType) -> Field; } - + fn main(x: Field, y: Field) { assert(y == x); }"; @@ -549,18 +549,18 @@ fn check_trait_wrong_parameters_count() { trait Default { fn default(x: Field, y: Field) -> Self; } - + struct Foo { bar: Field, array: [Field; 2], } - + impl Default for Foo { fn default(x: Field) -> Self { Self { bar: x, array: [x, x] } } } - + fn main() { } "; @@ -629,16 +629,16 @@ fn check_impl_struct_not_trait() { struct Default { x: Field, - z: Field, + z: Field, } - + // Default is a struct not a trait impl Default for Foo { fn default(x: Field, y: Field) -> Self { Self { bar: x, array: [x,y] } } } - + fn main() {} "; let errors = get_program_errors(src); @@ -664,23 +664,23 @@ fn check_trait_duplicate_declaration() { trait Default { fn default(x: Field, y: Field) -> Self; } - + struct Foo { bar: Field, array: [Field; 2], } - + impl Default for Foo { fn default(x: Field,y: Field) -> Self { Self { bar: x, array: [x,y] } } } - - + + trait Default { fn default(x: Field) -> Self; } - + fn main() { }"; let errors = get_program_errors(src); @@ -712,7 +712,7 @@ fn check_trait_duplicate_implementation() { struct Foo { bar: Field, } - + impl Default for Foo { } impl Default for Foo { @@ -743,18 +743,18 @@ fn check_trait_duplicate_implementation_with_alias() { let src = " trait Default { } - + struct MyStruct { } - + type MyType = MyStruct; - + impl Default for MyStruct { } - + impl Default for MyType { } - + fn main() { } "; @@ -807,7 +807,7 @@ fn check_trait_as_type_as_fn_parameter() { } impl Eq for Foo { - fn eq(self, other: Foo) -> bool { self.a == other.a } + fn eq(self, other: Foo) -> bool { self.a == other.a } } fn test_eq(x: impl Eq) -> bool { @@ -836,11 +836,11 @@ fn check_trait_as_type_as_two_fn_parameters() { } impl Eq for Foo { - fn eq(self, other: Foo) -> bool { self.a == other.a } + fn eq(self, other: Foo) -> bool { self.a == other.a } } impl Test for u64 { - fn test(self) -> bool { self == self } + fn test(self) -> bool { self == self } } fn test_eq(x: impl Eq, y: impl Test) -> bool { @@ -1425,7 +1425,7 @@ fn specify_function_types_with_turbofish() { fn generic_func() -> (T, U) where T: Default, U: Default { (T::default(), U::default()) } - + fn main() { let _ = generic_func::(); } @@ -1452,13 +1452,13 @@ fn specify_method_types_with_turbofish() { struct Foo { inner: T } - + impl Foo { fn generic_method(_self: Self) -> U where U: Default { U::default() } } - + fn main() { let foo: Foo = Foo { inner: 1 }; let _ = foo.generic_method::(); @@ -1521,13 +1521,13 @@ fn incorrect_turbofish_count_method_call() { struct Foo { inner: T } - + impl Foo { fn generic_method(_self: Self) -> U where U: Default { U::default() } } - + fn main() { let foo: Foo = Foo { inner: 1 }; let _ = foo.generic_method::(); @@ -1603,7 +1603,7 @@ fn numeric_generic_binary_operation_type_mismatch() { let mut check: bool = true; check = N; check - } + } "#; let errors = get_program_errors(src); assert_eq!(errors.len(), 1); @@ -1765,7 +1765,7 @@ fn numeric_generic_used_in_nested_type_pass() { } pub struct InnerNumeric { inner: [u64; N], - } + } "#; assert_no_errors(src); } @@ -1782,13 +1782,13 @@ fn numeric_generic_used_in_trait() { c: Field, d: T, } - + impl Deserialize for MyType { fn deserialize(fields: [Field; N], other: T) -> Self { MyType { a: fields[0], b: fields[1], c: fields[2], d: other } } } - + trait Deserialize { fn deserialize(fields: [Field; N], other: T) -> Self; } @@ -1809,17 +1809,17 @@ fn numeric_generic_in_trait_impl_with_extra_impl_generics() { c: Field, d: T, } - + // Make sure that `T` is placed before `N` as we want to test that the order of the generics is correctly maintained. // `N` is used first in the trait impl generics (`Deserialize for MyType`). // We want to make sure that the compiler correctly accounts for that `N` has a numeric kind - // while `T` has a normal kind. + // while `T` has a normal kind. impl Deserialize for MyType where T: Default { fn deserialize(fields: [Field; N]) -> Self { MyType { a: fields[0], b: fields[1], c: fields[2], d: T::default() } } } - + trait Deserialize { fn deserialize(fields: [Field; N]) -> Self; } @@ -2026,7 +2026,7 @@ fn impl_stricter_than_trait_no_trait_method_constraints() { // is a `DefCollectorErrorKind::ImplIsStricterThanTrait` error. let src = r#" trait Serialize { - // We want to make sure we trigger the error when override a trait method + // We want to make sure we trigger the error when override a trait method // which itself has no trait constraints. fn serialize(self) -> [Field; N]; } @@ -2131,14 +2131,14 @@ fn impl_stricter_than_trait_different_object_generics() { } impl Bar for () { - fn bar_good() - where - OtherOption>: OtherTrait, + fn bar_good() + where + OtherOption>: OtherTrait, Option: MyTrait { } - fn bar_bad() - where - OtherOption>: OtherTrait, + fn bar_bad() + where + OtherOption>: OtherTrait, Option: MyTrait { } fn array_good() where [A; 8]: MyTrait { } @@ -3522,7 +3522,7 @@ fn constrained_reference_to_unconstrained() { let x_ref = &mut x; if x == 5 { unsafe { - mut_ref_input(x_ref, y); + mut_ref_input(x_ref, y); } } @@ -3722,6 +3722,5 @@ fn use_numeric_generic_in_trait_method() { "#; let errors = get_program_errors(src); - println!("{errors:?}"); assert_eq!(errors.len(), 0); } diff --git a/test_programs/compile_success_empty/regression_4436/src/main.nr b/test_programs/compile_success_empty/regression_4436/src/main.nr index 834ea3250cc..336d0f1f4ed 100644 --- a/test_programs/compile_success_empty/regression_4436/src/main.nr +++ b/test_programs/compile_success_empty/regression_4436/src/main.nr @@ -3,8 +3,8 @@ trait LibTrait { fn get_constant() -> Field; } -global STRUCT_A_LEN: Field = 3; -global STRUCT_B_LEN: Field = 5; +global STRUCT_A_LEN: u32 = 3; +global STRUCT_B_LEN: u32 = 5; struct StructA; struct StructB; diff --git a/test_programs/execution_success/fold_basic/src/main.nr b/test_programs/execution_success/fold_basic/src/main.nr index 6c17120660b..440779d2460 100644 --- a/test_programs/execution_success/fold_basic/src/main.nr +++ b/test_programs/execution_success/fold_basic/src/main.nr @@ -1,7 +1,9 @@ fn main(x: Field, y: pub Field) { let z = foo(x, y); let z2 = foo(x, y); + let z3 = foo(x, y); assert(z == z2); + assert(z2 == z3); } #[fold]