diff --git a/.aztec-sync-commit b/.aztec-sync-commit index 031d3484b51..f60456adac1 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -79995c84e0f88c1ee72876fd21c50c33830597fc +bcec12dbf79b658406dc21083f8fdeef8962085e diff --git a/.github/scripts/cargo-binstall-install.sh b/.github/scripts/cargo-binstall-install.sh index 55d90904ca3..5cbf2cda221 100755 --- a/.github/scripts/cargo-binstall-install.sh +++ b/.github/scripts/cargo-binstall-install.sh @@ -1,4 +1,9 @@ #!/usr/bin/env bash set -eu -curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash +cd $(dirname "$0") + +CARGO_BINSTALL_CHECK=$(./command-check.sh cargo-binstall) +if [ $CARGO_BINSTALL_CHECK != "true" ]; then + curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash +fi diff --git a/.github/scripts/command-check.sh b/.github/scripts/command-check.sh new file mode 100755 index 00000000000..ebe2fa52bde --- /dev/null +++ b/.github/scripts/command-check.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -eu + +command -v $1 >/dev/null 2>&1 && echo "true" || { echo >&2 "$1 is not installed" && echo "false"; } diff --git a/acvm-repo/acir/codegen/acir.cpp b/acvm-repo/acir/codegen/acir.cpp index ef5baf076a0..a789a0f0c47 100644 --- a/acvm-repo/acir/codegen/acir.cpp +++ b/acvm-repo/acir/codegen/acir.cpp @@ -572,6 +572,16 @@ namespace Program { static BinaryIntOp bincodeDeserialize(std::vector); }; + struct Not { + Program::MemoryAddress destination; + Program::MemoryAddress source; + Program::IntegerBitSize bit_size; + + friend bool operator==(const Not&, const Not&); + std::vector bincodeSerialize() const; + static Not bincodeDeserialize(std::vector); + }; + struct Cast { Program::MemoryAddress destination; Program::MemoryAddress source; @@ -727,7 +737,7 @@ namespace Program { static Stop bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const BrilligOpcode&, const BrilligOpcode&); std::vector bincodeSerialize() const; @@ -5110,6 +5120,50 @@ Program::BrilligOpcode::BinaryIntOp serde::Deserializable BrilligOpcode::Not::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BrilligOpcode::Not BrilligOpcode::Not::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BrilligOpcode::Not &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.source, serializer); + serde::Serializable::serialize(obj.bit_size, serializer); +} + +template <> +template +Program::BrilligOpcode::Not serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Not obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.source = serde::Deserializable::deserialize(deserializer); + obj.bit_size = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Program { inline bool operator==(const BrilligOpcode::Cast &lhs, const BrilligOpcode::Cast &rhs) { diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index d7f0f5f6f1f..848d7bda84b 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -13,7 +13,9 @@ use serde::{Deserialize, Serialize}; mod black_box_function_call; mod memory_operation; -pub use black_box_function_call::{BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput}; +pub use black_box_function_call::{ + BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput, InvalidInputBitSize, +}; pub use memory_operation::{BlockId, MemOp}; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -40,7 +42,7 @@ pub enum Opcode { /// values which define the opcode. /// /// A general expression of assert-zero opcode is the following: - /// ``` + /// ```text /// \sum_{i,j} {q_M}_{i,j}w_iw_j + \sum_i q_iw_i +q_c = 0 /// ``` /// diff --git a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index 333bab419c8..f527522cceb 100644 --- a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -1,6 +1,8 @@ use crate::native_types::Witness; -use crate::BlackBoxFunc; +use crate::{AcirField, BlackBoxFunc}; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use thiserror::Error; // Note: Some functions will not use all of the witness // So we need to supply how many bits of the witness is needed @@ -13,8 +15,8 @@ pub enum ConstantOrWitnessEnum { #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct FunctionInput { - pub input: ConstantOrWitnessEnum, - pub num_bits: u32, + input: ConstantOrWitnessEnum, + num_bits: u32, } impl FunctionInput { @@ -25,6 +27,14 @@ impl FunctionInput { } } + pub fn input(self) -> ConstantOrWitnessEnum { + self.input + } + + pub fn input_ref(&self) -> &ConstantOrWitnessEnum { + &self.input + } + pub fn num_bits(&self) -> u32 { self.num_bits } @@ -32,9 +42,25 @@ impl FunctionInput { pub fn witness(witness: Witness, num_bits: u32) -> FunctionInput { FunctionInput { input: ConstantOrWitnessEnum::Witness(witness), num_bits } } +} + +#[derive(Clone, PartialEq, Eq, Debug, Error)] +#[error("FunctionInput value has too many bits: value: {value}, {value_num_bits} >= {max_bits}")] +pub struct InvalidInputBitSize { + pub value: String, + pub value_num_bits: u32, + pub max_bits: u32, +} - pub fn constant(value: F, num_bits: u32) -> FunctionInput { - FunctionInput { input: ConstantOrWitnessEnum::Constant(value), num_bits } +impl FunctionInput { + pub fn constant(value: F, max_bits: u32) -> Result, InvalidInputBitSize> { + if value.num_bits() <= max_bits { + Ok(FunctionInput { input: ConstantOrWitnessEnum::Constant(value), num_bits: max_bits }) + } else { + let value_num_bits = value.num_bits(); + let value = format!("{}", value); + Err(InvalidInputBitSize { value, value_num_bits, max_bits }) + } } } diff --git a/acvm-repo/acir/src/lib.rs b/acvm-repo/acir/src/lib.rs index 845a1d6ad5a..36331427b9f 100644 --- a/acvm-repo/acir/src/lib.rs +++ b/acvm-repo/acir/src/lib.rs @@ -12,6 +12,7 @@ pub use acir_field; pub use acir_field::{AcirField, FieldElement}; pub use brillig; pub use circuit::black_box_functions::BlackBoxFunc; +pub use circuit::opcodes::InvalidInputBitSize; #[cfg(test)] mod reflection { diff --git a/acvm-repo/acir/tests/test_program_serialization.rs b/acvm-repo/acir/tests/test_program_serialization.rs index 838886a03ce..2b6ea83fafa 100644 --- a/acvm-repo/acir/tests/test_program_serialization.rs +++ b/acvm-repo/acir/tests/test_program_serialization.rs @@ -62,13 +62,13 @@ fn multi_scalar_mul_circuit() { let multi_scalar_mul: Opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::MultiScalarMul { points: vec![ - FunctionInput::witness(Witness(1), 128), - FunctionInput::witness(Witness(2), 128), + FunctionInput::witness(Witness(1), FieldElement::max_num_bits()), + FunctionInput::witness(Witness(2), FieldElement::max_num_bits()), FunctionInput::witness(Witness(3), 1), ], scalars: vec![ - FunctionInput::witness(Witness(4), 128), - FunctionInput::witness(Witness(5), 128), + FunctionInput::witness(Witness(4), FieldElement::max_num_bits()), + FunctionInput::witness(Witness(5), FieldElement::max_num_bits()), ], outputs: (Witness(6), Witness(7), Witness(8)), }); @@ -91,10 +91,10 @@ fn multi_scalar_mul_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 11, 10, 0, 32, 8, 67, 43, 181, 15, 116, 232, - 142, 158, 210, 130, 149, 240, 112, 234, 212, 156, 78, 12, 39, 67, 71, 158, 142, 80, 29, 44, - 228, 66, 90, 168, 119, 189, 74, 115, 131, 174, 78, 115, 58, 124, 70, 254, 130, 59, 74, 253, - 68, 255, 255, 221, 39, 54, 221, 93, 91, 132, 193, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 11, 10, 0, 32, 8, 67, 43, 181, 15, 116, 255, + 227, 70, 74, 11, 86, 194, 195, 169, 83, 115, 58, 49, 156, 12, 29, 121, 58, 66, 117, 176, + 144, 11, 105, 161, 222, 245, 42, 205, 13, 186, 58, 205, 233, 240, 25, 249, 11, 238, 40, + 245, 19, 253, 255, 119, 159, 216, 103, 157, 249, 169, 193, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -214,12 +214,12 @@ fn simple_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 49, 10, 128, 48, 12, 108, 196, 138, 224, 230, - 75, 226, 15, 252, 140, 131, 139, 131, 136, 239, 111, 161, 9, 28, 165, 205, 210, 28, 132, - 36, 119, 16, 114, 9, 133, 130, 53, 7, 73, 29, 37, 107, 143, 80, 238, 148, 204, 99, 56, 200, - 111, 22, 227, 190, 83, 93, 16, 146, 193, 112, 22, 225, 34, 168, 205, 142, 174, 241, 218, - 206, 179, 121, 49, 188, 109, 57, 84, 191, 159, 255, 122, 63, 235, 199, 189, 190, 197, 237, - 13, 45, 1, 20, 245, 146, 30, 92, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 73, 10, 192, 48, 8, 140, 165, 91, 160, 183, + 126, 196, 254, 160, 159, 233, 161, 151, 30, 74, 200, 251, 19, 136, 130, 132, 196, 75, 28, + 16, 199, 17, 212, 65, 112, 5, 123, 14, 32, 190, 80, 230, 90, 130, 181, 155, 50, 142, 225, + 2, 187, 89, 40, 239, 157, 106, 2, 82, 116, 138, 51, 118, 239, 171, 222, 108, 232, 218, 139, + 125, 198, 179, 113, 83, 188, 29, 57, 86, 226, 239, 23, 159, 63, 104, 63, 238, 213, 45, 237, + 108, 244, 18, 195, 174, 252, 193, 92, 2, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -338,17 +338,17 @@ fn complex_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 81, 14, 194, 48, 8, 133, 118, 206, 26, 255, 60, - 129, 137, 30, 160, 211, 11, 120, 23, 227, 159, 70, 63, 61, 190, 146, 209, 140, 177, 46, - 251, 24, 77, 182, 151, 44, 116, 45, 16, 120, 64, 139, 208, 34, 252, 63, 228, 245, 134, 165, - 99, 73, 251, 30, 250, 72, 186, 55, 150, 113, 30, 26, 180, 243, 21, 75, 197, 232, 86, 16, - 163, 47, 16, 35, 136, 250, 47, 176, 222, 150, 117, 49, 229, 207, 103, 230, 167, 130, 118, - 190, 106, 254, 223, 178, 12, 154, 104, 50, 114, 48, 28, 188, 30, 82, 247, 236, 180, 23, 62, - 171, 236, 178, 185, 202, 27, 194, 216, 119, 36, 54, 142, 35, 185, 149, 203, 233, 18, 131, - 34, 220, 48, 167, 38, 176, 191, 18, 181, 168, 5, 63, 178, 179, 8, 123, 232, 186, 234, 254, - 126, 125, 158, 143, 175, 87, 148, 74, 51, 194, 73, 172, 207, 234, 28, 149, 157, 182, 149, - 144, 15, 70, 78, 23, 51, 122, 83, 190, 15, 208, 181, 70, 122, 152, 126, 56, 83, 244, 10, - 181, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 81, 14, 194, 48, 8, 133, 118, 186, 53, 241, + 207, 11, 152, 232, 1, 58, 189, 128, 119, 49, 254, 105, 244, 211, 227, 59, 50, 154, 49, 214, + 100, 31, 163, 201, 246, 146, 133, 174, 5, 10, 15, 72, 17, 122, 52, 221, 135, 188, 222, 177, + 116, 44, 105, 223, 195, 24, 73, 247, 206, 50, 46, 67, 139, 118, 190, 98, 169, 24, 221, 6, + 98, 244, 5, 98, 4, 81, 255, 21, 214, 219, 178, 46, 166, 252, 249, 204, 252, 84, 208, 207, + 215, 158, 255, 107, 150, 141, 38, 154, 140, 28, 76, 7, 111, 132, 212, 61, 65, 201, 116, 86, + 217, 101, 115, 11, 226, 62, 99, 223, 145, 88, 56, 205, 228, 102, 127, 239, 53, 6, 69, 184, + 97, 78, 109, 96, 127, 37, 106, 81, 11, 126, 100, 103, 17, 14, 48, 116, 213, 227, 243, 254, + 190, 158, 63, 175, 40, 149, 102, 132, 179, 88, 95, 212, 57, 42, 59, 109, 43, 33, 31, 140, + 156, 46, 102, 244, 230, 124, 31, 97, 104, 141, 244, 48, 253, 1, 180, 46, 168, 159, 181, 6, + 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index b03b6715abe..3570a36a7e7 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -1,6 +1,6 @@ use acir::{ circuit::{ - opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput}, + opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum}, Circuit, Opcode, }, native_types::Witness, @@ -73,10 +73,13 @@ impl RangeOptimizer { } } - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: - FunctionInput { input: ConstantOrWitnessEnum::Witness(witness), num_bits }, - }) => Some((*witness, *num_bits)), + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) => { + if let ConstantOrWitnessEnum::Witness(witness) = input.input() { + Some((witness, input.num_bits())) + } else { + None + } + } _ => None, }) else { @@ -106,17 +109,28 @@ impl RangeOptimizer { let mut new_order_list = Vec::with_capacity(order_list.len()); let mut optimized_opcodes = Vec::with_capacity(self.circuit.opcodes.len()); for (idx, opcode) in self.circuit.opcodes.into_iter().enumerate() { - let (witness, num_bits) = match opcode { - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: - FunctionInput { input: ConstantOrWitnessEnum::Witness(w), num_bits: bits }, - }) => (w, bits), - _ => { - // If its not the range opcode, add it to the opcode - // list and continue; + let (witness, num_bits) = { + // If its not the range opcode, add it to the opcode + // list and continue; + let mut push_non_range_opcode = || { optimized_opcodes.push(opcode.clone()); new_order_list.push(order_list[idx]); - continue; + }; + + match opcode { + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) => { + match input.input() { + ConstantOrWitnessEnum::Witness(witness) => (witness, input.num_bits()), + _ => { + push_non_range_opcode(); + continue; + } + } + } + _ => { + push_non_range_opcode(); + continue; + } } }; // If we've already applied the range constraint for this witness then skip this opcode. diff --git a/acvm-repo/acvm/src/pwg/blackbox/bigint.rs b/acvm-repo/acvm/src/pwg/blackbox/bigint.rs index 1bce4aa6c5e..ccad3510682 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/bigint.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/bigint.rs @@ -27,7 +27,7 @@ impl AcvmBigIntSolver { ) -> Result<(), OpcodeResolutionError> { let bytes = inputs .iter() - .map(|input| input_to_value(initial_witness, *input).unwrap().to_u128() as u8) + .map(|input| input_to_value(initial_witness, *input, false).unwrap().to_u128() as u8) .collect::>(); self.bigint_solver.bigint_from_bytes(&bytes, modulus, output)?; Ok(()) diff --git a/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs b/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs index c290faeaa4a..9e511571275 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs @@ -15,11 +15,11 @@ pub(super) fn multi_scalar_mul( outputs: (Witness, Witness, Witness), ) -> Result<(), OpcodeResolutionError> { let points: Result, _> = - points.iter().map(|input| input_to_value(initial_witness, *input)).collect(); + points.iter().map(|input| input_to_value(initial_witness, *input, false)).collect(); let points: Vec<_> = points?.into_iter().collect(); let scalars: Result, _> = - scalars.iter().map(|input| input_to_value(initial_witness, *input)).collect(); + scalars.iter().map(|input| input_to_value(initial_witness, *input, false)).collect(); let mut scalars_lo = Vec::new(); let mut scalars_hi = Vec::new(); for (i, scalar) in scalars?.into_iter().enumerate() { @@ -47,12 +47,12 @@ pub(super) fn embedded_curve_add( input2: [FunctionInput; 3], outputs: (Witness, Witness, Witness), ) -> Result<(), OpcodeResolutionError> { - let input1_x = input_to_value(initial_witness, input1[0])?; - let input1_y = input_to_value(initial_witness, input1[1])?; - let input1_infinite = input_to_value(initial_witness, input1[2])?; - let input2_x = input_to_value(initial_witness, input2[0])?; - let input2_y = input_to_value(initial_witness, input2[1])?; - let input2_infinite = input_to_value(initial_witness, input2[2])?; + let input1_x = input_to_value(initial_witness, input1[0], false)?; + let input1_y = input_to_value(initial_witness, input1[1], false)?; + let input1_infinite = input_to_value(initial_witness, input1[2], false)?; + let input2_x = input_to_value(initial_witness, input2[0], false)?; + let input2_y = input_to_value(initial_witness, input2[1], false)?; + let input2_infinite = input_to_value(initial_witness, input2[2], false)?; let (res_x, res_y, res_infinite) = backend.ec_add( &input1_x, &input1_y, diff --git a/acvm-repo/acvm/src/pwg/blackbox/hash.rs b/acvm-repo/acvm/src/pwg/blackbox/hash.rs index b51139f76b7..234ab6162ca 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/hash.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/hash.rs @@ -34,7 +34,7 @@ fn get_hash_input( for input in inputs.iter() { let num_bits = input.num_bits() as usize; - let witness_assignment = input_to_value(initial_witness, *input)?; + let witness_assignment = input_to_value(initial_witness, *input, false)?; let bytes = witness_assignment.fetch_nearest_bytes(num_bits); message_input.extend(bytes); } @@ -42,7 +42,8 @@ fn get_hash_input( // Truncate the message if there is a `message_size` parameter given match message_size { Some(input) => { - let num_bytes_to_take = input_to_value(initial_witness, *input)?.to_u128() as usize; + let num_bytes_to_take = + input_to_value(initial_witness, *input, false)?.to_u128() as usize; // If the number of bytes to take is more than the amount of bytes available // in the message, then we error. @@ -78,7 +79,7 @@ fn to_u32_array( ) -> Result<[u32; N], OpcodeResolutionError> { let mut result = [0; N]; for (it, input) in result.iter_mut().zip(inputs) { - let witness_value = input_to_value(initial_witness, *input)?; + let witness_value = input_to_value(initial_witness, *input, false)?; *it = witness_value.to_u128() as u32; } Ok(result) @@ -133,7 +134,7 @@ pub(crate) fn solve_poseidon2_permutation_opcode( // Read witness assignments let mut state = Vec::new(); for input in inputs.iter() { - let witness_assignment = input_to_value(initial_witness, *input)?; + let witness_assignment = input_to_value(initial_witness, *input, false)?; state.push(witness_assignment); } diff --git a/acvm-repo/acvm/src/pwg/blackbox/logic.rs b/acvm-repo/acvm/src/pwg/blackbox/logic.rs index 7ce0827d932..8468b0ca27a 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/logic.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/logic.rs @@ -51,8 +51,11 @@ fn solve_logic_opcode( result: Witness, logic_op: impl Fn(F, F) -> F, ) -> Result<(), OpcodeResolutionError> { - let w_l_value = input_to_value(initial_witness, *a)?; - let w_r_value = input_to_value(initial_witness, *b)?; + // TODO(https://github.com/noir-lang/noir/issues/5985): re-enable these once we figure out how to combine these with existing + // noirc_frontend/noirc_evaluator overflow error messages + let skip_bitsize_checks = true; + let w_l_value = input_to_value(initial_witness, *a, skip_bitsize_checks)?; + let w_r_value = input_to_value(initial_witness, *b, skip_bitsize_checks)?; let assignment = logic_op(w_l_value, w_r_value); insert_value(&result, assignment, initial_witness) diff --git a/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/mod.rs index def4216fe15..8b8bfc5cfc5 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -42,11 +42,11 @@ fn first_missing_assignment( inputs: &[FunctionInput], ) -> Option { inputs.iter().find_map(|input| { - if let ConstantOrWitnessEnum::Witness(witness) = input.input { - if witness_assignments.contains_key(&witness) { + if let ConstantOrWitnessEnum::Witness(ref witness) = input.input_ref() { + if witness_assignments.contains_key(witness) { None } else { - Some(witness) + Some(*witness) } } else { None @@ -108,7 +108,7 @@ pub(crate) fn solve( for (it, input) in state.iter_mut().zip(inputs.as_ref()) { let num_bits = input.num_bits() as usize; assert_eq!(num_bits, 64); - let witness_assignment = input_to_value(initial_witness, *input)?; + let witness_assignment = input_to_value(initial_witness, *input, false)?; let lane = witness_assignment.try_to_u64(); *it = lane.unwrap(); } diff --git a/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs b/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs index b1b95393b19..654814bf92d 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs @@ -17,7 +17,7 @@ pub(super) fn pedersen( outputs: (Witness, Witness), ) -> Result<(), OpcodeResolutionError> { let scalars: Result, _> = - inputs.iter().map(|input| input_to_value(initial_witness, *input)).collect(); + inputs.iter().map(|input| input_to_value(initial_witness, *input, false)).collect(); let scalars: Vec<_> = scalars?.into_iter().collect(); let (res_x, res_y) = backend.pedersen_commitment(&scalars, domain_separator)?; @@ -36,7 +36,7 @@ pub(super) fn pedersen_hash( output: Witness, ) -> Result<(), OpcodeResolutionError> { let scalars: Result, _> = - inputs.iter().map(|input| input_to_value(initial_witness, *input)).collect(); + inputs.iter().map(|input| input_to_value(initial_witness, *input, false)).collect(); let scalars: Vec<_> = scalars?.into_iter().collect(); let res = backend.pedersen_hash(&scalars, domain_separator)?; diff --git a/acvm-repo/acvm/src/pwg/blackbox/range.rs b/acvm-repo/acvm/src/pwg/blackbox/range.rs index 054730bb6c0..4f9be14360e 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/range.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/range.rs @@ -8,7 +8,10 @@ pub(crate) fn solve_range_opcode( initial_witness: &WitnessMap, input: &FunctionInput, ) -> Result<(), OpcodeResolutionError> { - let w_value = input_to_value(initial_witness, *input)?; + // TODO(https://github.com/noir-lang/noir/issues/5985): + // re-enable bitsize checks + let skip_bitsize_checks = true; + let w_value = input_to_value(initial_witness, *input, skip_bitsize_checks)?; if w_value.num_bits() > input.num_bits() { return Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, diff --git a/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs b/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs index 4f8e88373ba..a856303d065 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs @@ -21,8 +21,8 @@ pub(crate) fn schnorr_verify( message: &[FunctionInput], output: Witness, ) -> Result<(), OpcodeResolutionError> { - let public_key_x: &F = &input_to_value(initial_witness, public_key_x)?; - let public_key_y: &F = &input_to_value(initial_witness, public_key_y)?; + let public_key_x: &F = &input_to_value(initial_witness, public_key_x, false)?; + let public_key_y: &F = &input_to_value(initial_witness, public_key_y, false)?; let signature = to_u8_array(initial_witness, signature)?; let message = to_u8_vec(initial_witness, message)?; diff --git a/acvm-repo/acvm/src/pwg/blackbox/utils.rs b/acvm-repo/acvm/src/pwg/blackbox/utils.rs index 9b9157421e5..b966cb0cc5d 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/utils.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/utils.rs @@ -8,7 +8,7 @@ pub(crate) fn to_u8_array( ) -> Result<[u8; N], OpcodeResolutionError> { let mut result = [0; N]; for (it, input) in result.iter_mut().zip(inputs) { - let witness_value_bytes = input_to_value(initial_witness, *input)?.to_be_bytes(); + let witness_value_bytes = input_to_value(initial_witness, *input, false)?.to_be_bytes(); let byte = witness_value_bytes .last() .expect("Field element must be represented by non-zero amount of bytes"); @@ -23,7 +23,7 @@ pub(crate) fn to_u8_vec( ) -> Result, OpcodeResolutionError> { let mut result = Vec::with_capacity(inputs.len()); for input in inputs { - let witness_value_bytes = input_to_value(initial_witness, *input)?.to_be_bytes(); + let witness_value_bytes = input_to_value(initial_witness, *input, false)?.to_be_bytes(); let byte = witness_value_bytes .last() .expect("Field element must be represented by non-zero amount of bytes"); diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index 647c11bd3c3..c73893ceea6 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -6,7 +6,9 @@ use acir::{ brillig::ForeignCallResult, circuit::{ brillig::{BrilligBytecode, BrilligFunctionId}, - opcodes::{AcirFunctionId, BlockId, ConstantOrWitnessEnum, FunctionInput}, + opcodes::{ + AcirFunctionId, BlockId, ConstantOrWitnessEnum, FunctionInput, InvalidInputBitSize, + }, AssertionPayload, ErrorSelector, ExpressionOrMemory, Opcode, OpcodeLocation, RawAssertionPayload, ResolvedAssertionPayload, STRING_ERROR_SELECTOR, }, @@ -128,6 +130,11 @@ pub enum OpcodeResolutionError { }, #[error("Index out of bounds, array has size {array_size:?}, but index was {index:?}")] IndexOutOfBounds { opcode_location: ErrorLocation, index: u32, array_size: u32 }, + #[error("Cannot solve opcode: {invalid_input_bit_size}")] + InvalidInputBitSize { + opcode_location: ErrorLocation, + invalid_input_bit_size: InvalidInputBitSize, + }, #[error("Failed to solve blackbox function: {0}, reason: {1}")] BlackBoxFunctionFailed(BlackBoxFunc, String), #[error("Failed to solve brillig function")] @@ -152,6 +159,15 @@ impl From for OpcodeResolutionError { } } +impl From for OpcodeResolutionError { + fn from(invalid_input_bit_size: InvalidInputBitSize) -> Self { + Self::InvalidInputBitSize { + opcode_location: ErrorLocation::Unresolved, + invalid_input_bit_size, + } + } +} + pub struct ACVM<'a, F, B: BlackBoxFunctionSolver> { status: ACVMStatus, @@ -387,6 +403,13 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { *opcode_index = ErrorLocation::Resolved(location); *assertion_payload = self.extract_assertion_payload(location); } + OpcodeResolutionError::InvalidInputBitSize { + opcode_location: opcode_index, + .. + } => { + let location = OpcodeLocation::Acir(self.instruction_pointer()); + *opcode_index = ErrorLocation::Resolved(location); + } // All other errors are thrown normally. _ => (), }; @@ -633,12 +656,31 @@ pub fn witness_to_value( } } +// TODO(https://github.com/noir-lang/noir/issues/5985): +// remove skip_bitsize_checks pub fn input_to_value( initial_witness: &WitnessMap, input: FunctionInput, + skip_bitsize_checks: bool, ) -> Result> { - match input.input { - ConstantOrWitnessEnum::Witness(witness) => Ok(*witness_to_value(initial_witness, witness)?), + match input.input() { + ConstantOrWitnessEnum::Witness(witness) => { + let initial_value = *witness_to_value(initial_witness, witness)?; + if skip_bitsize_checks || initial_value.num_bits() <= input.num_bits() { + Ok(initial_value) + } else { + let value_num_bits = initial_value.num_bits(); + let value = initial_value.to_string(); + Err(OpcodeResolutionError::InvalidInputBitSize { + opcode_location: ErrorLocation::Unresolved, + invalid_input_bit_size: InvalidInputBitSize { + value, + value_num_bits, + max_bits: input.num_bits(), + }, + }) + } + } ConstantOrWitnessEnum::Constant(value) => Ok(value), } } diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index 41e28882993..766d374c43c 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -19,6 +19,7 @@ use acvm_blackbox_solver::StubbedBlackBoxSolver; use bn254_blackbox_solver::{field_from_hex, Bn254BlackBoxSolver, POSEIDON2_CONFIG}; use brillig_vm::brillig::HeapValueType; +use num_bigint::BigUint; use proptest::arbitrary::any; use proptest::prelude::*; use proptest::result::maybe_ok; @@ -835,15 +836,15 @@ fn constant_or_witness_to_function_inputs( xs: Vec, offset: usize, num_bits: Option, -) -> Vec> { +) -> Result>, OpcodeResolutionError> { let num_bits = num_bits.unwrap_or(FieldElement::max_num_bits()); xs.into_iter() .enumerate() .map(|(i, (x, use_constant))| { if use_constant { - FunctionInput::constant(x, num_bits) + FunctionInput::constant(x, num_bits).map_err(From::from) } else { - FunctionInput::witness(Witness((i + offset) as u32), num_bits) + Ok(FunctionInput::witness(Witness((i + offset) as u32), num_bits)) } }) .collect() @@ -869,9 +870,11 @@ fn solve_array_input_blackbox_call( num_outputs: usize, num_bits: Option, f: F, -) -> Vec +) -> Result, OpcodeResolutionError> where - F: FnOnce((Vec>, Vec)) -> BlackBoxFuncCall, + F: FnOnce( + (Vec>, Vec), + ) -> Result, OpcodeResolutionError>, { let initial_witness_vec: Vec<_> = inputs.iter().enumerate().map(|(i, (x, _))| (Witness(i as u32), *x)).collect(); @@ -880,8 +883,8 @@ where .collect(); let initial_witness = WitnessMap::from(BTreeMap::from_iter(initial_witness_vec)); - let inputs = constant_or_witness_to_function_inputs(inputs, 0, num_bits); - let op = Opcode::BlackBoxFuncCall(f((inputs.clone(), outputs.clone()))); + let inputs = constant_or_witness_to_function_inputs(inputs, 0, num_bits)?; + let op = Opcode::BlackBoxFuncCall(f((inputs.clone(), outputs.clone()))?); let opcodes = vec![op]; let unconstrained_functions = vec![]; let mut acvm = @@ -890,10 +893,10 @@ where assert_eq!(solver_status, ACVMStatus::Solved); let witness_map = acvm.finalize(); - outputs + Ok(outputs .iter() .map(|witness| *witness_map.get(witness).expect("all witnesses to be set")) - .collect() + .collect()) } prop_compose! { @@ -978,7 +981,7 @@ fn bigint_solve_binary_op_opt( modulus: Vec, lhs: Vec, rhs: Vec, -) -> Vec { +) -> Result, OpcodeResolutionError> { let initial_witness_vec: Vec<_> = lhs .iter() .chain(rhs.iter()) @@ -993,8 +996,8 @@ fn bigint_solve_binary_op_opt( .collect(); let initial_witness = WitnessMap::from(BTreeMap::from_iter(initial_witness_vec)); - let lhs = constant_or_witness_to_function_inputs(lhs, 0, None); - let rhs = constant_or_witness_to_function_inputs(rhs, lhs.len(), None); + let lhs = constant_or_witness_to_function_inputs(lhs, 0, None)?; + let rhs = constant_or_witness_to_function_inputs(rhs, lhs.len(), None)?; let to_op_input = if middle_op.is_some() { 2 } else { 0 }; @@ -1025,10 +1028,10 @@ fn bigint_solve_binary_op_opt( let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved); let witness_map = acvm.finalize(); - output_witnesses + Ok(output_witnesses .iter() .map(|witness| *witness_map.get(witness).expect("all witnesses to be set")) - .collect() + .collect()) } // Solve the given BlackBoxFuncCall with witnesses: 1, 2 as x, y, resp. @@ -1037,10 +1040,13 @@ fn solve_blackbox_func_call( blackbox_func_call: impl Fn( Option, Option, - ) -> BlackBoxFuncCall, + ) -> Result< + BlackBoxFuncCall, + OpcodeResolutionError, + >, lhs: (FieldElement, bool), // if false, use a Witness rhs: (FieldElement, bool), // if false, use a Witness -) -> FieldElement { +) -> Result> { let (lhs, lhs_constant) = lhs; let (rhs, rhs_constant) = rhs; @@ -1057,7 +1063,7 @@ fn solve_blackbox_func_call( rhs_opt = Some(rhs); } - let op = Opcode::BlackBoxFuncCall(blackbox_func_call(lhs_opt, rhs_opt)); + let op = Opcode::BlackBoxFuncCall(blackbox_func_call(lhs_opt, rhs_opt)?); let opcodes = vec![op]; let unconstrained_functions = vec![]; let mut acvm = @@ -1066,60 +1072,60 @@ fn solve_blackbox_func_call( assert_eq!(solver_status, ACVMStatus::Solved); let witness_map = acvm.finalize(); - witness_map[&Witness(3)] + Ok(witness_map[&Witness(3)]) } // N inputs // 32 outputs fn sha256_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (function_inputs, outputs) = function_inputs_and_outputs; - BlackBoxFuncCall::SHA256 { + Ok(BlackBoxFuncCall::SHA256 { inputs: function_inputs, outputs: outputs.try_into().expect("SHA256 returns 32 outputs"), - } + }) } // N inputs // 32 outputs fn blake2s_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (function_inputs, outputs) = function_inputs_and_outputs; - BlackBoxFuncCall::Blake2s { + Ok(BlackBoxFuncCall::Blake2s { inputs: function_inputs, outputs: outputs.try_into().expect("Blake2s returns 32 outputs"), - } + }) } // N inputs // 32 outputs fn blake3_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (function_inputs, outputs) = function_inputs_and_outputs; - BlackBoxFuncCall::Blake3 { + Ok(BlackBoxFuncCall::Blake3 { inputs: function_inputs, outputs: outputs.try_into().expect("Blake3 returns 32 outputs"), - } + }) } // variable inputs // 32 outputs fn keccak256_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (function_inputs, outputs) = function_inputs_and_outputs; let function_inputs_len = function_inputs.len(); - BlackBoxFuncCall::Keccak256 { + Ok(BlackBoxFuncCall::Keccak256 { inputs: function_inputs, var_message_size: FunctionInput::constant( function_inputs_len.into(), FieldElement::max_num_bits(), - ), + )?, outputs: outputs.try_into().expect("Keccak256 returns 32 outputs"), - } + }) } // var_message_size is the number of bytes to take @@ -1131,65 +1137,65 @@ fn keccak256_op( // 32 outputs fn keccak256_invalid_message_size_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (function_inputs, outputs) = function_inputs_and_outputs; let function_inputs_len = function_inputs.len(); - BlackBoxFuncCall::Keccak256 { + Ok(BlackBoxFuncCall::Keccak256 { inputs: function_inputs, var_message_size: FunctionInput::constant( (function_inputs_len - 1).into(), FieldElement::max_num_bits(), - ), + )?, outputs: outputs.try_into().expect("Keccak256 returns 32 outputs"), - } + }) } // 25 inputs // 25 outputs fn keccakf1600_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (function_inputs, outputs) = function_inputs_and_outputs; - BlackBoxFuncCall::Keccakf1600 { + Ok(BlackBoxFuncCall::Keccakf1600 { inputs: function_inputs.try_into().expect("Keccakf1600 expects 25 inputs"), outputs: outputs.try_into().expect("Keccakf1600 returns 25 outputs"), - } + }) } // N inputs // N outputs fn poseidon2_permutation_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (inputs, outputs) = function_inputs_and_outputs; let len = inputs.len() as u32; - BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len } + Ok(BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len }) } // N inputs // N outputs fn poseidon2_permutation_invalid_len_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (inputs, outputs) = function_inputs_and_outputs; let len = (inputs.len() as u32) + 1; - BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len } + Ok(BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len }) } // 24 inputs (16 + 8) // 8 outputs fn sha256_compression_op( function_inputs_and_outputs: (Vec>, Vec), -) -> BlackBoxFuncCall { +) -> Result, OpcodeResolutionError> { let (function_inputs, outputs) = function_inputs_and_outputs; let mut function_inputs = function_inputs.into_iter(); let inputs = core::array::from_fn(|_| function_inputs.next().unwrap()); let hash_values = core::array::from_fn(|_| function_inputs.next().unwrap()); - BlackBoxFuncCall::Sha256Compression { + Ok(BlackBoxFuncCall::Sha256Compression { inputs: Box::new(inputs), hash_values: Box::new(hash_values), outputs: outputs.try_into().unwrap(), - } + }) } fn into_repr_vec(fields: T) -> Vec @@ -1209,13 +1215,13 @@ where fn run_both_poseidon2_permutations( inputs: Vec, -) -> (Vec, Vec) { +) -> Result<(Vec, Vec), OpcodeResolutionError> { let result = solve_array_input_blackbox_call( inputs.clone(), inputs.len(), None, poseidon2_permutation_op, - ); + )?; let poseidon2_t = POSEIDON2_CONFIG.t as usize; let poseidon2_d = 5; @@ -1238,7 +1244,7 @@ fn run_both_poseidon2_permutations( let expected_result = external_poseidon2.permutation(&into_repr_vec(drop_use_constant(&inputs))); - (into_repr_vec(result), expected_result) + Ok((into_repr_vec(result), expected_result)) } // Using the given BigInt modulus, solve the following circuit: @@ -1254,7 +1260,7 @@ fn bigint_solve_binary_op( lhs: Vec, rhs: Vec, ) -> Vec { - bigint_solve_binary_op_opt(Some(middle_op), modulus, lhs, rhs) + bigint_solve_binary_op_opt(Some(middle_op), modulus, lhs, rhs).unwrap() } // Using the given BigInt modulus, solve the following circuit: @@ -1265,69 +1271,89 @@ fn bigint_solve_from_to_le_bytes( modulus: Vec, inputs: Vec, ) -> Vec { - bigint_solve_binary_op_opt(None, modulus, inputs, vec![]) + bigint_solve_binary_op_opt(None, modulus, inputs, vec![]).unwrap() } fn function_input_from_option( witness: Witness, opt_constant: Option, -) -> FunctionInput { +) -> Result, OpcodeResolutionError> { opt_constant - .map(|constant| FunctionInput::constant(constant, FieldElement::max_num_bits())) - .unwrap_or(FunctionInput::witness(witness, FieldElement::max_num_bits())) + .map(|constant| { + FunctionInput::constant(constant, FieldElement::max_num_bits()).map_err(From::from) + }) + .unwrap_or(Ok(FunctionInput::witness(witness, FieldElement::max_num_bits()))) } -fn and_op(x: Option, y: Option) -> BlackBoxFuncCall { - let lhs = function_input_from_option(Witness(1), x); - let rhs = function_input_from_option(Witness(2), y); - BlackBoxFuncCall::AND { lhs, rhs, output: Witness(3) } +fn and_op( + x: Option, + y: Option, +) -> Result, OpcodeResolutionError> { + let lhs = function_input_from_option(Witness(1), x)?; + let rhs = function_input_from_option(Witness(2), y)?; + Ok(BlackBoxFuncCall::AND { lhs, rhs, output: Witness(3) }) } -fn xor_op(x: Option, y: Option) -> BlackBoxFuncCall { - let lhs = function_input_from_option(Witness(1), x); - let rhs = function_input_from_option(Witness(2), y); - BlackBoxFuncCall::XOR { lhs, rhs, output: Witness(3) } +fn xor_op( + x: Option, + y: Option, +) -> Result, OpcodeResolutionError> { + let lhs = function_input_from_option(Witness(1), x)?; + let rhs = function_input_from_option(Witness(2), y)?; + Ok(BlackBoxFuncCall::XOR { lhs, rhs, output: Witness(3) }) } fn prop_assert_commutative( - op: impl Fn(Option, Option) -> BlackBoxFuncCall, + op: impl Fn( + Option, + Option, + ) -> Result, OpcodeResolutionError>, x: (FieldElement, bool), y: (FieldElement, bool), ) -> (FieldElement, FieldElement) { - (solve_blackbox_func_call(&op, x, y), solve_blackbox_func_call(&op, y, x)) + (solve_blackbox_func_call(&op, x, y).unwrap(), solve_blackbox_func_call(&op, y, x).unwrap()) } fn prop_assert_associative( - op: impl Fn(Option, Option) -> BlackBoxFuncCall, + op: impl Fn( + Option, + Option, + ) -> Result, OpcodeResolutionError>, x: (FieldElement, bool), y: (FieldElement, bool), z: (FieldElement, bool), use_constant_xy: bool, use_constant_yz: bool, ) -> (FieldElement, FieldElement) { - let f_xy = (solve_blackbox_func_call(&op, x, y), use_constant_xy); - let f_f_xy_z = solve_blackbox_func_call(&op, f_xy, z); + let f_xy = (solve_blackbox_func_call(&op, x, y).unwrap(), use_constant_xy); + let f_f_xy_z = solve_blackbox_func_call(&op, f_xy, z).unwrap(); - let f_yz = (solve_blackbox_func_call(&op, y, z), use_constant_yz); - let f_x_f_yz = solve_blackbox_func_call(&op, x, f_yz); + let f_yz = (solve_blackbox_func_call(&op, y, z).unwrap(), use_constant_yz); + let f_x_f_yz = solve_blackbox_func_call(&op, x, f_yz).unwrap(); (f_f_xy_z, f_x_f_yz) } fn prop_assert_identity_l( - op: impl Fn(Option, Option) -> BlackBoxFuncCall, + op: impl Fn( + Option, + Option, + ) -> Result, OpcodeResolutionError>, op_identity: (FieldElement, bool), x: (FieldElement, bool), ) -> (FieldElement, FieldElement) { - (solve_blackbox_func_call(op, op_identity, x), x.0) + (solve_blackbox_func_call(op, op_identity, x).unwrap(), x.0) } fn prop_assert_zero_l( - op: impl Fn(Option, Option) -> BlackBoxFuncCall, + op: impl Fn( + Option, + Option, + ) -> Result, OpcodeResolutionError>, op_zero: (FieldElement, bool), x: (FieldElement, bool), ) -> (FieldElement, FieldElement) { - (solve_blackbox_func_call(op, op_zero, x), FieldElement::zero()) + (solve_blackbox_func_call(op, op_zero, x).unwrap(), FieldElement::zero()) } // Test that varying one of the inputs produces a different result @@ -1341,14 +1367,19 @@ fn prop_assert_injective( op: F, ) -> (bool, String) where - F: FnOnce((Vec>, Vec)) -> BlackBoxFuncCall + F: FnOnce( + (Vec>, Vec), + ) + -> Result, OpcodeResolutionError> + Clone, { let equal_inputs = drop_use_constant_eq(&inputs, &distinct_inputs); let message = format!("not injective:\n{:?}\n{:?}", &inputs, &distinct_inputs); let outputs_not_equal = solve_array_input_blackbox_call(inputs, num_outputs, num_bits, op.clone()) - != solve_array_input_blackbox_call(distinct_inputs, num_outputs, num_bits, op); + .expect("injectivity test operations to have valid input") + != solve_array_input_blackbox_call(distinct_inputs, num_outputs, num_bits, op) + .expect("injectivity test operations to have valid input"); (equal_inputs || outputs_not_equal, message) } @@ -1381,12 +1412,12 @@ prop_compose! { -> (Vec, Vec) { let (_size, patch_location, patch_value) = size_and_patch; let (inputs, distinct_inputs) = inputs_distinct_inputs; + let modulus = if let Some(max_input_bits) = max_input_bits { + 1u128 << max_input_bits + } else { + 1 + }; let to_input = |(x, use_constant)| { - let modulus = if let Some(max_input_bits) = max_input_bits { - 2u128 << max_input_bits - } else { - 1 - }; (FieldElement::from(x % modulus), use_constant) }; let inputs: Vec<_> = inputs.into_iter().map(to_input).collect(); @@ -1397,9 +1428,11 @@ prop_compose! { let distinct_inputs_len = distinct_inputs.len(); let positive_patch_value = std::cmp::max(patch_value, 1); if distinct_inputs_len != 0 { - distinct_inputs[patch_location % distinct_inputs_len].0 += FieldElement::from(positive_patch_value) + let previous_input = &mut distinct_inputs[patch_location % distinct_inputs_len].0; + let patched_input: BigUint = (*previous_input + FieldElement::from(positive_patch_value)).into_repr().into(); + *previous_input = FieldElement::from_be_bytes_reduce(&(patched_input % BigUint::from(modulus)).to_bytes_be()); } else { - distinct_inputs.push((FieldElement::zero(), true)) + distinct_inputs.push((FieldElement::zero(), true)); } } @@ -1411,17 +1444,17 @@ prop_compose! { fn poseidon2_permutation_zeroes() { let use_constants: [bool; 4] = [false; 4]; let inputs: Vec<_> = [FieldElement::zero(); 4].into_iter().zip(use_constants).collect(); - let (result, expected_result) = run_both_poseidon2_permutations(inputs); + let (results, expected_results) = run_both_poseidon2_permutations(inputs).unwrap(); - let internal_expected_result = vec![ + let internal_expected_results = vec![ field_from_hex("18DFB8DC9B82229CFF974EFEFC8DF78B1CE96D9D844236B496785C698BC6732E"), field_from_hex("095C230D1D37A246E8D2D5A63B165FE0FADE040D442F61E25F0590E5FB76F839"), field_from_hex("0BB9545846E1AFA4FA3C97414A60A20FC4949F537A68CCECA34C5CE71E28AA59"), field_from_hex("18A4F34C9C6F99335FF7638B82AEED9018026618358873C982BBDDE265B2ED6D"), ]; - assert_eq!(expected_result, into_repr_vec(internal_expected_result)); - assert_eq!(result, expected_result); + assert_eq!(expected_results, into_repr_vec(internal_expected_results)); + assert_eq!(results, expected_results); } #[test] @@ -1434,7 +1467,7 @@ fn sha256_zeros() { .into_iter() .map(|x: u128| FieldElement::from(x)) .collect(); - assert_eq!(results, expected_results); + assert_eq!(results, Ok(expected_results)); } #[test] @@ -1452,7 +1485,7 @@ fn sha256_compression_zeros() { .into_iter() .map(|x: u128| FieldElement::from(x)) .collect(); - assert_eq!(results, expected_results); + assert_eq!(results, Ok(expected_results)); } #[test] @@ -1465,7 +1498,7 @@ fn blake2s_zeros() { .into_iter() .map(|x: u128| FieldElement::from(x)) .collect(); - assert_eq!(results, expected_results); + assert_eq!(results, Ok(expected_results)); } #[test] @@ -1478,7 +1511,7 @@ fn blake3_zeros() { .into_iter() .map(|x: u128| FieldElement::from(x)) .collect(); - assert_eq!(results, expected_results); + assert_eq!(results, Ok(expected_results)); } #[test] @@ -1491,7 +1524,7 @@ fn keccak256_zeros() { .into_iter() .map(|x: u128| FieldElement::from(x)) .collect(); - assert_eq!(results, expected_results); + assert_eq!(results, Ok(expected_results)); } #[test] @@ -1533,7 +1566,7 @@ fn keccakf1600_zeros() { .map(|x: u128| FieldElement::from(x)) .collect(); - assert_eq!(results, expected_results); + assert_eq!(results, Ok(expected_results)); } // NOTE: an "average" bigint is large, so consider increasing the number of proptest shrinking @@ -1570,13 +1603,13 @@ proptest! { // test that AND(x, x) == x #[test] fn and_self_identity(x in field_element()) { - prop_assert_eq!(solve_blackbox_func_call(and_op, x, x), x.0); + prop_assert_eq!(solve_blackbox_func_call(and_op, x, x).unwrap(), x.0); } // test that XOR(x, x) == 0 #[test] fn xor_self_zero(x in field_element()) { - prop_assert_eq!(solve_blackbox_func_call(xor_op, x, x), FieldElement::zero()); + prop_assert_eq!(solve_blackbox_func_call(xor_op, x, x).unwrap(), FieldElement::zero()); } #[test] @@ -1606,7 +1639,7 @@ proptest! { #[test] fn poseidon2_permutation_matches_external_impl(inputs in proptest::collection::vec(field_element(), 4)) { - let (result, expected_result) = run_both_poseidon2_permutations(inputs); + let (result, expected_result) = run_both_poseidon2_permutations(inputs).unwrap(); prop_assert_eq!(result, expected_result) } diff --git a/acvm-repo/acvm_js/src/execute.rs b/acvm-repo/acvm_js/src/execute.rs index 98a0c4c3abe..c3627d0eff5 100644 --- a/acvm-repo/acvm_js/src/execute.rs +++ b/acvm-repo/acvm_js/src/execute.rs @@ -201,6 +201,10 @@ impl<'a, B: BlackBoxFunctionSolver> ProgramExecutor<'a, B> { opcode_location: ErrorLocation::Resolved(opcode_location), .. } => Some(vec![*opcode_location]), + OpcodeResolutionError::InvalidInputBitSize { + opcode_location: ErrorLocation::Resolved(opcode_location), + .. + } => Some(vec![*opcode_location]), OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { Some(call_stack.clone()) } diff --git a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index ba26e3d139a..60e4c8d5829 100644 --- a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,14 +2,14 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 81, 14, 194, 48, 8, 133, 118, 206, 26, 255, 60, 129, 137, 30, 160, 211, - 11, 120, 23, 227, 159, 70, 63, 61, 190, 146, 209, 140, 177, 46, 251, 24, 77, 182, 151, 44, 116, 45, 16, 120, 64, 139, - 208, 34, 252, 63, 228, 245, 134, 165, 99, 73, 251, 30, 250, 72, 186, 55, 150, 113, 30, 26, 180, 243, 21, 75, 197, 232, - 86, 16, 163, 47, 16, 35, 136, 250, 47, 176, 222, 150, 117, 49, 229, 207, 103, 230, 167, 130, 118, 190, 106, 254, 223, - 178, 12, 154, 104, 50, 114, 48, 28, 188, 30, 82, 247, 236, 180, 23, 62, 171, 236, 178, 185, 202, 27, 194, 216, 119, - 36, 54, 142, 35, 185, 149, 203, 233, 18, 131, 34, 220, 48, 167, 38, 176, 191, 18, 181, 168, 5, 63, 178, 179, 8, 123, - 232, 186, 234, 254, 126, 125, 158, 143, 175, 87, 148, 74, 51, 194, 73, 172, 207, 234, 28, 149, 157, 182, 149, 144, 15, - 70, 78, 23, 51, 122, 83, 190, 15, 208, 181, 70, 122, 152, 126, 56, 83, 244, 10, 181, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 81, 14, 194, 48, 8, 133, 118, 186, 53, 241, 207, 11, 152, 232, 1, 58, 189, + 128, 119, 49, 254, 105, 244, 211, 227, 59, 50, 154, 49, 214, 100, 31, 163, 201, 246, 146, 133, 174, 5, 10, 15, 72, 17, + 122, 52, 221, 135, 188, 222, 177, 116, 44, 105, 223, 195, 24, 73, 247, 206, 50, 46, 67, 139, 118, 190, 98, 169, 24, + 221, 6, 98, 244, 5, 98, 4, 81, 255, 21, 214, 219, 178, 46, 166, 252, 249, 204, 252, 84, 208, 207, 215, 158, 255, 107, + 150, 141, 38, 154, 140, 28, 76, 7, 111, 132, 212, 61, 65, 201, 116, 86, 217, 101, 115, 11, 226, 62, 99, 223, 145, 88, + 56, 205, 228, 102, 127, 239, 53, 6, 69, 184, 97, 78, 109, 96, 127, 37, 106, 81, 11, 126, 100, 103, 17, 14, 48, 116, + 213, 227, 243, 254, 190, 158, 63, 175, 40, 149, 102, 132, 179, 88, 95, 212, 57, 42, 59, 109, 43, 33, 31, 140, 156, 46, + 102, 244, 230, 124, 31, 97, 104, 141, 244, 48, 253, 1, 180, 46, 168, 159, 181, 6, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/acvm-repo/acvm_js/test/shared/foreign_call.ts b/acvm-repo/acvm_js/test/shared/foreign_call.ts index 498a914cff4..9bf57535c87 100644 --- a/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,11 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 49, 10, 128, 48, 12, 108, 196, 138, 224, 230, 75, 226, 15, 252, 140, 131, - 139, 131, 136, 239, 111, 161, 9, 28, 165, 205, 210, 28, 132, 36, 119, 16, 114, 9, 133, 130, 53, 7, 73, 29, 37, 107, - 143, 80, 238, 148, 204, 99, 56, 200, 111, 22, 227, 190, 83, 93, 16, 146, 193, 112, 22, 225, 34, 168, 205, 142, 174, - 241, 218, 206, 179, 121, 49, 188, 109, 57, 84, 191, 159, 255, 122, 63, 235, 199, 189, 190, 197, 237, 13, 45, 1, 20, - 245, 146, 30, 92, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 73, 10, 192, 48, 8, 140, 165, 91, 160, 183, 126, 196, 254, 160, 159, 233, + 161, 151, 30, 74, 200, 251, 19, 136, 130, 132, 196, 75, 28, 16, 199, 17, 212, 65, 112, 5, 123, 14, 32, 190, 80, 230, + 90, 130, 181, 155, 50, 142, 225, 2, 187, 89, 40, 239, 157, 106, 2, 82, 116, 138, 51, 118, 239, 171, 222, 108, 232, + 218, 139, 125, 198, 179, 113, 83, 188, 29, 57, 86, 226, 239, 23, 159, 63, 104, 63, 238, 213, 45, 237, 108, 244, 18, + 195, 174, 252, 193, 92, 2, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts b/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts index 80fbf14e8f1..ffb9952b136 100644 --- a/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts +++ b/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts @@ -1,8 +1,8 @@ // See `multi_scalar_mul_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 11, 10, 0, 32, 8, 67, 43, 181, 15, 116, 232, 142, 158, 210, 130, 149, 240, - 112, 234, 212, 156, 78, 12, 39, 67, 71, 158, 142, 80, 29, 44, 228, 66, 90, 168, 119, 189, 74, 115, 131, 174, 78, 115, - 58, 124, 70, 254, 130, 59, 74, 253, 68, 255, 255, 221, 39, 54, 221, 93, 91, 132, 193, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 11, 10, 0, 32, 8, 67, 43, 181, 15, 116, 255, 227, 70, 74, 11, 86, 194, + 195, 169, 83, 115, 58, 49, 156, 12, 29, 121, 58, 66, 117, 176, 144, 11, 105, 161, 222, 245, 42, 205, 13, 186, 58, 205, + 233, 240, 25, 249, 11, 238, 40, 245, 19, 253, 255, 119, 159, 216, 103, 157, 249, 169, 193, 0, 0, 0, ]); export const initialWitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/acvm-repo/brillig/src/opcodes.rs b/acvm-repo/brillig/src/opcodes.rs index ac469cebf87..45df2aca2d8 100644 --- a/acvm-repo/brillig/src/opcodes.rs +++ b/acvm-repo/brillig/src/opcodes.rs @@ -188,6 +188,11 @@ pub enum BrilligOpcode { lhs: MemoryAddress, rhs: MemoryAddress, }, + Not { + destination: MemoryAddress, + source: MemoryAddress, + bit_size: IntegerBitSize, + }, Cast { destination: MemoryAddress, source: MemoryAddress, diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 04519279d52..07d0ea02ad4 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -213,6 +213,13 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { self.increment_program_counter() } } + Opcode::Not { destination, source, bit_size } => { + if let Err(error) = self.process_not(*source, *destination, *bit_size) { + self.fail(error) + } else { + self.increment_program_counter() + } + } Opcode::Cast { destination: destination_address, source: source_address, bit_size } => { let source_value = self.memory.read(*source_address); let casted_value = self.cast(*bit_size, source_value); @@ -709,6 +716,36 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { Ok(()) } + fn process_not( + &mut self, + source: MemoryAddress, + destination: MemoryAddress, + op_bit_size: IntegerBitSize, + ) -> Result<(), String> { + let (value, bit_size) = self + .memory + .read(source) + .extract_integer() + .ok_or("Not opcode source is not an integer")?; + + if bit_size != op_bit_size { + return Err(format!( + "Not opcode source bit size {} does not match expected bit size {}", + bit_size, op_bit_size + )); + } + + let negated_value = if let IntegerBitSize::U128 = bit_size { + !value + } else { + let bit_size: u32 = bit_size.into(); + let mask = (1_u128 << bit_size as u128) - 1; + (!value) & mask + }; + self.memory.write(destination, MemoryValue::new_integer(negated_value, bit_size)); + Ok(()) + } + /// Casts a value to a different bit size. fn cast(&self, target_bit_size: BitSize, source_value: MemoryValue) -> MemoryValue { match (source_value, target_bit_size) { @@ -952,6 +989,62 @@ mod tests { assert_eq!(casted_value.to_field(), (2_u128.pow(8) - 1).into()); } + #[test] + fn not_opcode() { + let calldata: Vec = vec![(1_usize).into()]; + + let opcodes = &[ + Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1u64), + }, + Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + Opcode::CalldataCopy { + destination_address: MemoryAddress(0), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), + }, + Opcode::Cast { + destination: MemoryAddress::from(1), + source: MemoryAddress::from(0), + bit_size: BitSize::Integer(IntegerBitSize::U128), + }, + Opcode::Not { + destination: MemoryAddress::from(1), + source: MemoryAddress::from(1), + bit_size: IntegerBitSize::U128, + }, + Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + ]; + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::Finished { return_data_offset: 1, return_data_size: 1 }); + + let VM { memory, .. } = vm; + + let (negated_value, _) = memory + .read(MemoryAddress::from(1)) + .extract_integer() + .expect("Expected integer as the output of Not"); + assert_eq!(negated_value, !1_u128); + } + #[test] fn mov_opcode() { let calldata: Vec = vec![(1u128).into(), (2u128).into(), (3u128).into()]; diff --git a/aztec_macros/src/transforms/events.rs b/aztec_macros/src/transforms/events.rs index d753bb43471..878bc37393a 100644 --- a/aztec_macros/src/transforms/events.rs +++ b/aztec_macros/src/transforms/events.rs @@ -1,4 +1,7 @@ -use noirc_frontend::ast::{Documented, ItemVisibility, NoirFunction, NoirTraitImpl, TraitImplItem}; +use noirc_errors::Span; +use noirc_frontend::ast::{ + Documented, ItemVisibility, NoirFunction, NoirTraitImpl, TraitImplItem, TraitImplItemKind, +}; use noirc_frontend::macros_api::{NodeInterner, StructId}; use noirc_frontend::token::SecondaryAttribute; use noirc_frontend::{ @@ -67,30 +70,37 @@ pub fn generate_event_impls( event_byte_len, empty_spans, )?; - event_interface_trait_impl.items.push(Documented::not_documented( - TraitImplItem::Function(generate_fn_get_event_type_id( + event_interface_trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(generate_fn_get_event_type_id( event_type.as_str(), event_len, empty_spans, )?), - )); - event_interface_trait_impl.items.push(Documented::not_documented( - TraitImplItem::Function(generate_fn_private_to_be_bytes( + span: Span::default(), + })); + event_interface_trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(generate_fn_private_to_be_bytes( event_type.as_str(), event_byte_len, empty_spans, )?), - )); - event_interface_trait_impl.items.push(Documented::not_documented( - TraitImplItem::Function(generate_fn_to_be_bytes( + span: Span::default(), + })); + event_interface_trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(generate_fn_to_be_bytes( event_type.as_str(), event_byte_len, empty_spans, )?), - )); - event_interface_trait_impl.items.push(Documented::not_documented( - TraitImplItem::Function(generate_fn_emit(event_type.as_str(), empty_spans)?), - )); + span: Span::default(), + })); + event_interface_trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(generate_fn_emit( + event_type.as_str(), + empty_spans, + )?), + span: Span::default(), + })); submodule.contents.trait_impls.push(event_interface_trait_impl); let serialize_trait_impl = generate_trait_impl_serialize( diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs index 6e95efa637c..d9c4a594fc6 100644 --- a/aztec_macros/src/transforms/note_interface.rs +++ b/aztec_macros/src/transforms/note_interface.rs @@ -1,7 +1,7 @@ use noirc_errors::Span; use noirc_frontend::ast::{ Documented, ItemVisibility, LetStatement, NoirFunction, NoirStruct, PathKind, StructField, - TraitImplItem, TypeImpl, UnresolvedTypeData, UnresolvedTypeExpression, + TraitImplItem, TraitImplItemKind, TypeImpl, UnresolvedTypeData, UnresolvedTypeExpression, }; use noirc_frontend::{ graph::CrateId, @@ -153,9 +153,10 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(Documented::not_documented(TraitImplItem::Function( - note_serialize_content_fn, - ))); + trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(note_serialize_content_fn), + span: note_interface_impl_span, + })); let note_deserialize_content_fn = generate_note_deserialize_content( ¬e_type, @@ -165,9 +166,10 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(Documented::not_documented(TraitImplItem::Function( - note_deserialize_content_fn, - ))); + trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(note_deserialize_content_fn), + span: note_interface_impl_span, + })); let note_properties_struct = generate_note_properties_struct( ¬e_type, @@ -196,9 +198,10 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl - .items - .push(Documented::not_documented(TraitImplItem::Function(get_header_fn))); + trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(get_header_fn), + span: note_interface_impl_span, + })); } if !check_trait_method_implemented(trait_impl, "set_header") { let set_header_fn = generate_note_set_header( @@ -207,18 +210,20 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl - .items - .push(Documented::not_documented(TraitImplItem::Function(set_header_fn))); + trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(set_header_fn), + span: note_interface_impl_span, + })); } if !check_trait_method_implemented(trait_impl, "get_note_type_id") { let note_type_id = compute_note_type_id(¬e_type); let get_note_type_id_fn = generate_get_note_type_id(note_type_id, note_interface_impl_span, empty_spans)?; - trait_impl - .items - .push(Documented::not_documented(TraitImplItem::Function(get_note_type_id_fn))); + trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(get_note_type_id_fn), + span: note_interface_impl_span, + })); } if !check_trait_method_implemented(trait_impl, "compute_note_hiding_point") { @@ -227,9 +232,10 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(Documented::not_documented(TraitImplItem::Function( - compute_note_hiding_point_fn, - ))); + trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(compute_note_hiding_point_fn), + span: note_interface_impl_span, + })); } if !check_trait_method_implemented(trait_impl, "to_be_bytes") { @@ -240,9 +246,10 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl - .items - .push(Documented::not_documented(TraitImplItem::Function(to_be_bytes_fn))); + trait_impl.items.push(Documented::not_documented(TraitImplItem { + kind: TraitImplItemKind::Function(to_be_bytes_fn), + span: note_interface_impl_span, + })); } } diff --git a/aztec_macros/src/utils/ast_utils.rs b/aztec_macros/src/utils/ast_utils.rs index b68946ec020..eeb8e1f7d78 100644 --- a/aztec_macros/src/utils/ast_utils.rs +++ b/aztec_macros/src/utils/ast_utils.rs @@ -3,7 +3,7 @@ use noirc_frontend::ast::{ BinaryOpKind, CallExpression, CastExpression, Expression, ExpressionKind, FunctionReturnType, Ident, IndexExpression, InfixExpression, Lambda, MemberAccessExpression, MethodCallExpression, NoirTraitImpl, Path, PathSegment, Pattern, PrefixExpression, Statement, StatementKind, - TraitImplItem, UnaryOp, UnresolvedType, UnresolvedTypeData, + TraitImplItemKind, UnaryOp, UnresolvedType, UnresolvedTypeData, }; use noirc_frontend::token::SecondaryAttribute; @@ -179,8 +179,8 @@ pub fn index_array(array: Ident, index: &str) -> Expression { } pub fn check_trait_method_implemented(trait_impl: &NoirTraitImpl, method_name: &str) -> bool { - trait_impl.items.iter().any(|item| match &item.item { - TraitImplItem::Function(func) => func.def.name.0.contents == method_name, + trait_impl.items.iter().any(|item| match &item.item.kind { + TraitImplItemKind::Function(func) => func.def.name.0.contents == method_name, _ => false, }) } diff --git a/aztec_macros/src/utils/errors.rs b/aztec_macros/src/utils/errors.rs index 557d065cb25..c0b4310de96 100644 --- a/aztec_macros/src/utils/errors.rs +++ b/aztec_macros/src/utils/errors.rs @@ -29,7 +29,7 @@ impl From for MacroError { fn from(err: AztecMacroError) -> Self { match err { AztecMacroError::AztecDepNotFound {} => MacroError { - primary_message: "Aztec dependency not found. Please add aztec as a dependency in your Nargo.toml. For more information go to https://docs.aztec.network/developers/debugging/aztecnr-errors#aztec-dependency-not-found-please-add-aztec-as-a-dependency-in-your-nargotoml".to_owned(), + primary_message: "Aztec dependency not found. Please add aztec as a dependency in your Nargo.toml. For more information go to https://docs.aztec.network/reference/developer_references/common_errors/aztecnr-errors#aztec-dependency-not-found-please-add-aztec-as-a-dependency-in-your-nargotoml".to_owned(), secondary_message: None, span: None, }, diff --git a/aztec_macros/src/utils/parse_utils.rs b/aztec_macros/src/utils/parse_utils.rs index dce3af1402b..712afbc248b 100644 --- a/aztec_macros/src/utils/parse_utils.rs +++ b/aztec_macros/src/utils/parse_utils.rs @@ -6,9 +6,9 @@ use noirc_frontend::{ InfixExpression, LValue, Lambda, LetStatement, Literal, MemberAccessExpression, MethodCallExpression, ModuleDeclaration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Path, PathSegment, Pattern, PrefixExpression, Statement, - StatementKind, TraitImplItem, TraitItem, TypeImpl, UnresolvedGeneric, UnresolvedGenerics, - UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, - UseTree, UseTreeKind, + StatementKind, TraitImplItem, TraitImplItemKind, TraitItem, TypeImpl, UnresolvedGeneric, + UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, + UnresolvedTypeExpression, UseTree, UseTreeKind, }, parser::{Item, ItemKind, ParsedSubModule, ParserError}, ParsedModule, @@ -137,14 +137,20 @@ fn empty_trait_item(trait_item: &mut TraitItem) { } fn empty_trait_impl_item(trait_impl_item: &mut TraitImplItem) { + trait_impl_item.span = Default::default(); + + empty_trait_impl_item_kind(&mut trait_impl_item.kind); +} + +fn empty_trait_impl_item_kind(trait_impl_item: &mut TraitImplItemKind) { match trait_impl_item { - TraitImplItem::Function(noir_function) => empty_noir_function(noir_function), - TraitImplItem::Constant(name, typ, default_value) => { + TraitImplItemKind::Function(noir_function) => empty_noir_function(noir_function), + TraitImplItemKind::Constant(name, typ, default_value) => { empty_ident(name); empty_unresolved_type(typ); empty_expression(default_value); } - TraitImplItem::Type { name, alias } => { + TraitImplItemKind::Type { name, alias } => { empty_ident(name); empty_unresolved_type(alias); } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 36a3b34aeb0..85db1bd8b96 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -1,3 +1,5 @@ +use acvm::acir::brillig::MemoryAddress; + use crate::brillig::brillig_ir::{ brillig_variable::{BrilligVariable, BrilligVector, SingleAddrVariable}, BrilligBinaryOp, @@ -6,57 +8,37 @@ use crate::brillig::brillig_ir::{ use super::brillig_block::BrilligBlock; impl<'block> BrilligBlock<'block> { + fn write_variables(&mut self, write_pointer: MemoryAddress, variables: &[BrilligVariable]) { + for (index, variable) in variables.iter().enumerate() { + self.brillig_context.store_instruction(write_pointer, variable.extract_register()); + if index != variables.len() - 1 { + self.brillig_context.codegen_usize_op_in_place( + write_pointer, + BrilligBinaryOp::Add, + 1, + ); + } + } + } + pub(crate) fn slice_push_back_operation( &mut self, target_vector: BrilligVector, source_vector: BrilligVector, variables_to_insert: &[BrilligVariable], ) { - // First we need to allocate the target vector incrementing the size by variables_to_insert.len() - let source_size = self.brillig_context.codegen_make_vector_length(source_vector); - - let target_size = SingleAddrVariable::new_usize(self.brillig_context.allocate_register()); - self.brillig_context.codegen_usize_op( - source_size.address, - target_size.address, - BrilligBinaryOp::Add, + let write_pointer = self.brillig_context.allocate_register(); + self.brillig_context.call_prepare_vector_push_procedure( + source_vector, + target_vector, + write_pointer, variables_to_insert.len(), + true, ); - self.brillig_context.codegen_initialize_vector(target_vector, target_size); + self.write_variables(write_pointer, variables_to_insert); - // Now we copy the source vector into the target vector - let source_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(source_vector); - let target_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(target_vector); - - self.brillig_context.codegen_mem_copy( - source_vector_items_pointer, - target_vector_items_pointer, - source_size, - ); - - for (index, variable) in variables_to_insert.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); - self.brillig_context.memory_op_instruction( - target_index.address, - source_size.address, - target_index.address, - BrilligBinaryOp::Add, - ); - self.brillig_context.codegen_store_with_offset( - target_vector_items_pointer, - target_index, - variable.extract_register(), - ); - self.brillig_context.deallocate_single_addr(target_index); - } - - self.brillig_context.deallocate_single_addr(source_size); - self.brillig_context.deallocate_single_addr(target_size); - self.brillig_context.deallocate_register(source_vector_items_pointer); - self.brillig_context.deallocate_register(target_vector_items_pointer); + self.brillig_context.deallocate_register(write_pointer); } pub(crate) fn slice_push_front_operation( @@ -65,56 +47,30 @@ impl<'block> BrilligBlock<'block> { source_vector: BrilligVector, variables_to_insert: &[BrilligVariable], ) { - // First we need to allocate the target vector incrementing the size by variables_to_insert.len() - let source_size = self.brillig_context.codegen_make_vector_length(source_vector); - - let target_size = SingleAddrVariable::new_usize(self.brillig_context.allocate_register()); - self.brillig_context.codegen_usize_op( - source_size.address, - target_size.address, - BrilligBinaryOp::Add, - variables_to_insert.len(), - ); - - self.brillig_context.codegen_initialize_vector(target_vector, target_size); - - // Now we offset the target pointer by variables_to_insert.len() - let source_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(source_vector); - let target_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(target_vector); - - let destination_copy_pointer = self.brillig_context.allocate_register(); - self.brillig_context.codegen_usize_op( - target_vector_items_pointer, - destination_copy_pointer, - BrilligBinaryOp::Add, + let write_pointer = self.brillig_context.allocate_register(); + self.brillig_context.call_prepare_vector_push_procedure( + source_vector, + target_vector, + write_pointer, variables_to_insert.len(), + false, ); - // Now we copy the source vector into the target vector starting at index variables_to_insert.len() - self.brillig_context.codegen_mem_copy( - source_vector_items_pointer, - destination_copy_pointer, - source_size, - ); + self.write_variables(write_pointer, variables_to_insert); + self.brillig_context.deallocate_register(write_pointer); + } - // Then we write the items to insert at the start - for (index, variable) in variables_to_insert.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); - self.brillig_context.codegen_store_with_offset( - target_vector_items_pointer, - target_index, - variable.extract_register(), - ); - self.brillig_context.deallocate_single_addr(target_index); + fn read_variables(&mut self, read_pointer: MemoryAddress, variables: &[BrilligVariable]) { + for (index, variable) in variables.iter().enumerate() { + self.brillig_context.load_instruction(variable.extract_register(), read_pointer); + if index != variables.len() - 1 { + self.brillig_context.codegen_usize_op_in_place( + read_pointer, + BrilligBinaryOp::Add, + 1, + ); + } } - - self.brillig_context.deallocate_register(destination_copy_pointer); - self.brillig_context.deallocate_single_addr(source_size); - self.brillig_context.deallocate_single_addr(target_size); - self.brillig_context.deallocate_register(source_vector_items_pointer); - self.brillig_context.deallocate_register(target_vector_items_pointer); } pub(crate) fn slice_pop_front_operation( @@ -123,55 +79,17 @@ impl<'block> BrilligBlock<'block> { source_vector: BrilligVector, removed_items: &[BrilligVariable], ) { - // First we need to allocate the target vector decrementing the size by removed_items.len() - let source_size = self.brillig_context.codegen_make_vector_length(source_vector); - - let target_size = SingleAddrVariable::new_usize(self.brillig_context.allocate_register()); - self.brillig_context.codegen_usize_op( - source_size.address, - target_size.address, - BrilligBinaryOp::Sub, + let read_pointer = self.brillig_context.allocate_register(); + self.brillig_context.call_vector_pop_procedure( + source_vector, + target_vector, + read_pointer, removed_items.len(), + false, ); - self.brillig_context.codegen_initialize_vector(target_vector, target_size); - - // Now we offset the source pointer by removed_items.len() - let source_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(source_vector); - let target_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(target_vector); - - let source_copy_pointer = self.brillig_context.allocate_register(); - self.brillig_context.codegen_usize_op( - source_vector_items_pointer, - source_copy_pointer, - BrilligBinaryOp::Add, - removed_items.len(), - ); - - // Now we copy the source vector starting at index removed_items.len() into the target vector - self.brillig_context.codegen_mem_copy( - source_copy_pointer, - target_vector_items_pointer, - target_size, - ); - - for (index, variable) in removed_items.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); - self.brillig_context.codegen_load_with_offset( - source_vector_items_pointer, - target_index, - variable.extract_register(), - ); - self.brillig_context.deallocate_single_addr(target_index); - } - - self.brillig_context.deallocate_register(source_copy_pointer); - self.brillig_context.deallocate_single_addr(source_size); - self.brillig_context.deallocate_single_addr(target_size); - self.brillig_context.deallocate_register(source_vector_items_pointer); - self.brillig_context.deallocate_register(target_vector_items_pointer); + self.read_variables(read_pointer, removed_items); + self.brillig_context.deallocate_register(read_pointer); } pub(crate) fn slice_pop_back_operation( @@ -180,50 +98,17 @@ impl<'block> BrilligBlock<'block> { source_vector: BrilligVector, removed_items: &[BrilligVariable], ) { - // First we need to allocate the target vector decrementing the size by removed_items.len() - let source_size = self.brillig_context.codegen_make_vector_length(source_vector); - - let target_size = SingleAddrVariable::new_usize(self.brillig_context.allocate_register()); - self.brillig_context.codegen_usize_op( - source_size.address, - target_size.address, - BrilligBinaryOp::Sub, + let read_pointer = self.brillig_context.allocate_register(); + self.brillig_context.call_vector_pop_procedure( + source_vector, + target_vector, + read_pointer, removed_items.len(), + true, ); - self.brillig_context.codegen_initialize_vector(target_vector, target_size); - - // Now we copy all elements except the last items into the target vector - let source_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(source_vector); - let target_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(target_vector); - - self.brillig_context.codegen_mem_copy( - source_vector_items_pointer, - target_vector_items_pointer, - target_size, - ); - - for (index, variable) in removed_items.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); - self.brillig_context.memory_op_instruction( - target_index.address, - target_size.address, - target_index.address, - BrilligBinaryOp::Add, - ); - self.brillig_context.codegen_load_with_offset( - source_vector_items_pointer, - target_index, - variable.extract_register(), - ); - self.brillig_context.deallocate_single_addr(target_index); - } - self.brillig_context.deallocate_single_addr(source_size); - self.brillig_context.deallocate_single_addr(target_size); - self.brillig_context.deallocate_register(source_vector_items_pointer); - self.brillig_context.deallocate_register(target_vector_items_pointer); + self.read_variables(read_pointer, removed_items); + self.brillig_context.deallocate_register(read_pointer); } pub(crate) fn slice_insert_operation( @@ -233,95 +118,18 @@ impl<'block> BrilligBlock<'block> { index: SingleAddrVariable, items: &[BrilligVariable], ) { - // First we need to allocate the target vector incrementing the size by items.len() - let source_size = self.brillig_context.codegen_make_vector_length(source_vector); - - let target_size = SingleAddrVariable::new_usize(self.brillig_context.allocate_register()); - self.brillig_context.codegen_usize_op( - source_size.address, - target_size.address, - BrilligBinaryOp::Add, - items.len(), - ); - - self.brillig_context.codegen_initialize_vector(target_vector, target_size); - - // Copy the elements to the left of the index - let source_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(source_vector); - let target_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(target_vector); + let write_pointer = self.brillig_context.allocate_register(); - self.brillig_context.codegen_mem_copy( - source_vector_items_pointer, - target_vector_items_pointer, + self.brillig_context.call_prepare_vector_insert_procedure( + source_vector, + target_vector, index, - ); - - // Compute the source pointer just at the index - let source_pointer_at_index = self.brillig_context.allocate_register(); - self.brillig_context.memory_op_instruction( - source_vector_items_pointer, - index.address, - source_pointer_at_index, - BrilligBinaryOp::Add, - ); - - // Compute the target pointer after the inserted elements - let target_pointer_after_index = self.brillig_context.allocate_register(); - self.brillig_context.memory_op_instruction( - target_vector_items_pointer, - index.address, - target_pointer_after_index, - BrilligBinaryOp::Add, - ); - self.brillig_context.codegen_usize_op_in_place( - target_pointer_after_index, - BrilligBinaryOp::Add, + write_pointer, items.len(), ); - // Compute the number of elements to the right of the index - let item_count = self.brillig_context.allocate_register(); - self.brillig_context.memory_op_instruction( - source_size.address, - index.address, - item_count, - BrilligBinaryOp::Sub, - ); - - // Copy the elements to the right of the index - self.brillig_context.codegen_mem_copy( - source_pointer_at_index, - target_pointer_after_index, - SingleAddrVariable::new_usize(item_count), - ); - - // Write the items to insert starting at the index - for (subitem_index, variable) in items.iter().enumerate() { - let target_index = - self.brillig_context.make_usize_constant_instruction(subitem_index.into()); - self.brillig_context.memory_op_instruction( - target_index.address, - index.address, - target_index.address, - BrilligBinaryOp::Add, - ); - self.brillig_context.codegen_store_with_offset( - target_vector_items_pointer, - target_index, - variable.extract_register(), - ); - self.brillig_context.deallocate_single_addr(target_index); - } - - self.brillig_context.deallocate_register(source_pointer_at_index); - self.brillig_context.deallocate_register(target_pointer_after_index); - self.brillig_context.deallocate_register(item_count); - self.brillig_context.deallocate_single_addr(source_size); - self.brillig_context.deallocate_single_addr(target_size); - self.brillig_context.deallocate_register(source_vector_items_pointer); - self.brillig_context.deallocate_register(target_vector_items_pointer); + self.write_variables(write_pointer, items); + self.brillig_context.deallocate_register(write_pointer); } pub(crate) fn slice_remove_operation( @@ -331,100 +139,21 @@ impl<'block> BrilligBlock<'block> { index: SingleAddrVariable, removed_items: &[BrilligVariable], ) { - // First we need to allocate the target vector decrementing the size by removed_items.len() - let source_size = self.brillig_context.codegen_make_vector_length(source_vector); - - let target_size = SingleAddrVariable::new_usize(self.brillig_context.allocate_register()); - self.brillig_context.codegen_usize_op( - source_size.address, - target_size.address, - BrilligBinaryOp::Sub, - removed_items.len(), - ); - - self.brillig_context.codegen_initialize_vector(target_vector, target_size); - - // Copy the elements to the left of the index - let source_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(source_vector); - let target_vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(target_vector); - - self.brillig_context.codegen_mem_copy( - source_vector_items_pointer, - target_vector_items_pointer, - index, - ); - - // Compute the source pointer after the removed items - let source_pointer_after_index = self.brillig_context.allocate_register(); - self.brillig_context.memory_op_instruction( - source_vector_items_pointer, - index.address, - source_pointer_after_index, - BrilligBinaryOp::Add, - ); - self.brillig_context.codegen_usize_op_in_place( - source_pointer_after_index, - BrilligBinaryOp::Add, - removed_items.len(), - ); - - // Compute the target pointer at the index - let target_pointer_at_index = self.brillig_context.allocate_register(); + let read_pointer = self.brillig_context.codegen_make_vector_items_pointer(source_vector); self.brillig_context.memory_op_instruction( - target_vector_items_pointer, + read_pointer, index.address, - target_pointer_at_index, + read_pointer, BrilligBinaryOp::Add, ); + self.read_variables(read_pointer, removed_items); - // Compute the number of elements to the right of the index - let item_count = self.brillig_context.allocate_register(); - self.brillig_context.memory_op_instruction( - source_size.address, - index.address, - item_count, - BrilligBinaryOp::Sub, - ); - self.brillig_context.codegen_usize_op_in_place( - item_count, - BrilligBinaryOp::Sub, + self.brillig_context.call_vector_remove_procedure( + source_vector, + target_vector, + index, removed_items.len(), ); - - // Copy the elements to the right of the index - self.brillig_context.codegen_mem_copy( - source_pointer_after_index, - target_pointer_at_index, - SingleAddrVariable::new_usize(item_count), - ); - - // Get the removed items - for (subitem_index, variable) in removed_items.iter().enumerate() { - let target_index = - self.brillig_context.make_usize_constant_instruction(subitem_index.into()); - self.brillig_context.memory_op_instruction( - target_index.address, - index.address, - target_index.address, - BrilligBinaryOp::Add, - ); - self.brillig_context.codegen_load_with_offset( - source_vector_items_pointer, - target_index, - variable.extract_register(), - ); - self.brillig_context.deallocate_single_addr(target_index); - } - - self.brillig_context.deallocate_register(source_pointer_after_index); - self.brillig_context.deallocate_register(target_pointer_at_index); - self.brillig_context.deallocate_register(item_count); - self.brillig_context.deallocate_single_addr(source_size); - self.brillig_context.deallocate_single_addr(target_size); - self.brillig_context.deallocate_register(source_vector_items_pointer); - self.brillig_context.deallocate_register(target_vector_items_pointer); } } @@ -458,7 +187,6 @@ mod tests { let ssa = builder.finish(); let mut brillig_context = create_context(ssa.main_id); brillig_context.enter_context(Label::block(ssa.main_id, Id::test_new(0))); - brillig_context.disable_procedures(); let function_context = FunctionContext::new(ssa.main()); (ssa, function_context, brillig_context) diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index b52b239e6b9..d8065294b0c 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -112,10 +112,6 @@ impl BrilligContext { can_call_procedures: true, } } - /// Allows disabling procedures so tests don't need a linking pass - pub(crate) fn disable_procedures(&mut self) { - self.can_call_procedures = false; - } } /// Special brillig context to codegen compiler intrinsic shared procedures @@ -165,7 +161,8 @@ pub(crate) mod tests { use crate::brillig::brillig_ir::{BrilligBinaryOp, BrilligContext}; use crate::ssa::ir::function::FunctionId; - use super::artifact::{BrilligParameter, GeneratedBrillig, Label}; + use super::artifact::{BrilligParameter, GeneratedBrillig, Label, LabelType}; + use super::procedures::compile_procedure; use super::registers::Stack; use super::{BrilligOpcode, ReservedRegisters}; @@ -237,13 +234,17 @@ pub(crate) mod tests { returns: Vec, ) -> GeneratedBrillig { let artifact = context.artifact(); - let mut entry_point_artifact = BrilligContext::new_entry_point_artifact( - arguments, - returns, - FunctionId::test_new(0), - true, - ); + let mut entry_point_artifact = + BrilligContext::new_entry_point_artifact(arguments, returns, FunctionId::test_new(0)); entry_point_artifact.link_with(&artifact); + while let Some(unresolved_fn_label) = entry_point_artifact.first_unresolved_function_call() + { + let LabelType::Procedure(procedure_id) = unresolved_fn_label.label_type else { + panic!("Test functions cannot be linked with other functions"); + }; + let procedure_artifact = compile_procedure(procedure_id); + entry_point_artifact.link_with(&procedure_artifact); + } entry_point_artifact.finish() } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index bde128d0b6b..ff9b5ea67eb 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -18,12 +18,9 @@ impl BrilligContext { arguments: Vec, return_parameters: Vec, target_function: FunctionId, - disable_procedures: bool, ) -> BrilligArtifact { let mut context = BrilligContext::new(false); - if disable_procedures { - context.disable_procedures(); - } + context.codegen_entry_point(&arguments, &return_parameters); context.add_external_call_instruction(target_function); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs index faeade7fcf1..f196552b768 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs @@ -48,12 +48,12 @@ impl BrilligContext< result: SingleAddrVariable, ) { self.debug_show.not_instruction(input.address, input.bit_size, result.address); - // Compile !x as ((-1) - x) - let u_max = F::from(2_u128).pow(&F::from(input.bit_size as u128)) - F::one(); - let max = self.make_constant(u_max, input.bit_size); - - self.binary(max, input, result, BrilligBinaryOp::Sub); - self.deallocate_single_addr(max); + assert_eq!(input.bit_size, result.bit_size, "Not operands should have the same bit size"); + self.push_opcode(BrilligOpcode::Not { + destination: result.address, + source: input.address, + bit_size: input.bit_size.try_into().unwrap(), + }); } /// Utility method to perform a binary instruction with a memory address @@ -418,12 +418,6 @@ impl BrilligContext< var } - fn make_constant(&mut self, constant: F, bit_size: u32) -> SingleAddrVariable { - let var = SingleAddrVariable::new(self.allocate_register(), bit_size); - self.constant(var.address, var.bit_size, constant, false); - var - } - /// Returns a register which holds the value of an usize constant pub(crate) fn make_usize_constant_instruction(&mut self, constant: F) -> SingleAddrVariable { let register = self.allocate_register(); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs index d2a011f8aa5..32fe6725e56 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs @@ -1,12 +1,20 @@ mod array_copy; mod array_reverse; mod mem_copy; +mod prepare_vector_insert; +mod prepare_vector_push; mod vector_copy; +mod vector_pop; +mod vector_remove; use array_copy::compile_array_copy_procedure; use array_reverse::compile_array_reverse_procedure; use mem_copy::compile_mem_copy_procedure; +use prepare_vector_insert::compile_prepare_vector_insert_procedure; +use prepare_vector_push::compile_prepare_vector_push_procedure; use vector_copy::compile_vector_copy_procedure; +use vector_pop::compile_vector_pop_procedure; +use vector_remove::compile_vector_remove_procedure; use crate::brillig::brillig_ir::AcirField; @@ -25,6 +33,10 @@ pub(crate) enum ProcedureId { ArrayReverse, VectorCopy, MemCopy, + PrepareVectorPush(bool), + VectorPop(bool), + PrepareVectorInsert, + VectorRemove, } pub(crate) fn compile_procedure( @@ -38,6 +50,16 @@ pub(crate) fn compile_procedure( ProcedureId::ArrayCopy => compile_array_copy_procedure(&mut brillig_context), ProcedureId::ArrayReverse => compile_array_reverse_procedure(&mut brillig_context), ProcedureId::VectorCopy => compile_vector_copy_procedure(&mut brillig_context), + ProcedureId::PrepareVectorPush(push_back) => { + compile_prepare_vector_push_procedure(&mut brillig_context, push_back); + } + ProcedureId::VectorPop(pop_back) => { + compile_vector_pop_procedure(&mut brillig_context, pop_back); + } + ProcedureId::PrepareVectorInsert => { + compile_prepare_vector_insert_procedure(&mut brillig_context); + } + ProcedureId::VectorRemove => compile_vector_remove_procedure(&mut brillig_context), }; brillig_context.stop_instruction(); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_insert.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_insert.rs new file mode 100644 index 00000000000..d3a6855fa0f --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_insert.rs @@ -0,0 +1,134 @@ +use std::vec; + +use acvm::{acir::brillig::MemoryAddress, AcirField}; + +use super::ProcedureId; +use crate::brillig::brillig_ir::{ + brillig_variable::{BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, + registers::{RegisterAllocator, ScratchSpace}, + BrilligBinaryOp, BrilligContext, +}; + +impl BrilligContext { + /// It prepares a vector for a insert operation, leaving a hole at the index position which is returned as the write_pointer. + pub(crate) fn call_prepare_vector_insert_procedure( + &mut self, + source_vector: BrilligVector, + destination_vector: BrilligVector, + index: SingleAddrVariable, + write_pointer: MemoryAddress, + item_count: usize, + ) { + let source_vector_pointer_arg = MemoryAddress::from(ScratchSpace::start()); + let index_arg = MemoryAddress::from(ScratchSpace::start() + 1); + let item_count_arg = MemoryAddress::from(ScratchSpace::start() + 2); + let new_vector_pointer_return = MemoryAddress::from(ScratchSpace::start() + 3); + let write_pointer_return = MemoryAddress::from(ScratchSpace::start() + 4); + + self.mov_instruction(source_vector_pointer_arg, source_vector.pointer); + self.mov_instruction(index_arg, index.address); + self.usize_const_instruction(item_count_arg, item_count.into()); + + self.add_procedure_call_instruction(ProcedureId::PrepareVectorInsert); + + self.mov_instruction(destination_vector.pointer, new_vector_pointer_return); + self.mov_instruction(write_pointer, write_pointer_return); + } +} + +pub(super) fn compile_prepare_vector_insert_procedure( + brillig_context: &mut BrilligContext, +) { + let source_vector_pointer_arg = MemoryAddress::from(ScratchSpace::start()); + let index_arg = MemoryAddress::from(ScratchSpace::start() + 1); + let item_count_arg = MemoryAddress::from(ScratchSpace::start() + 2); + let new_vector_pointer_return = MemoryAddress::from(ScratchSpace::start() + 3); + let write_pointer_return = MemoryAddress::from(ScratchSpace::start() + 4); + + brillig_context.set_allocated_registers(vec![ + source_vector_pointer_arg, + index_arg, + item_count_arg, + new_vector_pointer_return, + write_pointer_return, + ]); + + let source_vector = BrilligVector { pointer: source_vector_pointer_arg }; + let target_vector = BrilligVector { pointer: new_vector_pointer_return }; + let index = SingleAddrVariable::new_usize(index_arg); + + // First we need to allocate the target vector incrementing the size by items.len() + let source_size = brillig_context.codegen_make_vector_length(source_vector); + + let target_size = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + brillig_context.memory_op_instruction( + source_size.address, + item_count_arg, + target_size.address, + BrilligBinaryOp::Add, + ); + + brillig_context.codegen_initialize_vector(target_vector, target_size); + + // Copy the elements to the left of the index + let source_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(source_vector); + let target_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(target_vector); + + brillig_context.codegen_mem_copy( + source_vector_items_pointer, + target_vector_items_pointer, + index, + ); + + // Compute the source pointer just at the index + let source_pointer_at_index = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + source_vector_items_pointer, + index_arg, + source_pointer_at_index, + BrilligBinaryOp::Add, + ); + + // Compute the target pointer after the inserted elements + brillig_context.memory_op_instruction( + target_vector_items_pointer, + index.address, + write_pointer_return, + BrilligBinaryOp::Add, + ); + let target_pointer_after_index = brillig_context.allocate_register(); + + brillig_context.memory_op_instruction( + write_pointer_return, + item_count_arg, + target_pointer_after_index, + BrilligBinaryOp::Add, + ); + + // Compute the number of elements to the right of the index + let item_count = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + source_size.address, + index.address, + item_count, + BrilligBinaryOp::Sub, + ); + + // Copy the elements to the right of the index + brillig_context.codegen_mem_copy( + source_pointer_at_index, + target_pointer_after_index, + SingleAddrVariable::new_usize(item_count), + ); + + brillig_context.deallocate_register(source_pointer_at_index); + brillig_context.deallocate_register(target_pointer_after_index); + brillig_context.deallocate_register(item_count); + brillig_context.deallocate_single_addr(source_size); + brillig_context.deallocate_single_addr(target_size); + brillig_context.deallocate_register(source_vector_items_pointer); + brillig_context.deallocate_register(target_vector_items_pointer); +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_push.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_push.rs new file mode 100644 index 00000000000..8af75712374 --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/prepare_vector_push.rs @@ -0,0 +1,111 @@ +use std::vec; + +use acvm::{acir::brillig::MemoryAddress, AcirField}; + +use super::ProcedureId; +use crate::brillig::brillig_ir::{ + brillig_variable::{BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, + registers::{RegisterAllocator, ScratchSpace}, + BrilligBinaryOp, BrilligContext, +}; + +impl BrilligContext { + /// Prepares a vector for a push operation, allocating a larger vector and copying the source vector into the destination vector. + /// It returns the write pointer to where to put the new items. + pub(crate) fn call_prepare_vector_push_procedure( + &mut self, + source_vector: BrilligVector, + destination_vector: BrilligVector, + write_pointer: MemoryAddress, + item_push_count: usize, + back: bool, + ) { + let source_vector_pointer_arg = MemoryAddress::from(ScratchSpace::start()); + let item_push_count_arg = MemoryAddress::from(ScratchSpace::start() + 1); + let new_vector_pointer_return = MemoryAddress::from(ScratchSpace::start() + 2); + let write_pointer_return = MemoryAddress::from(ScratchSpace::start() + 3); + + self.mov_instruction(source_vector_pointer_arg, source_vector.pointer); + self.usize_const_instruction(item_push_count_arg, item_push_count.into()); + + self.add_procedure_call_instruction(ProcedureId::PrepareVectorPush(back)); + + self.mov_instruction(destination_vector.pointer, new_vector_pointer_return); + self.mov_instruction(write_pointer, write_pointer_return); + } +} + +pub(super) fn compile_prepare_vector_push_procedure( + brillig_context: &mut BrilligContext, + push_back: bool, +) { + let source_vector_pointer_arg = MemoryAddress::from(ScratchSpace::start()); + let item_push_count_arg = MemoryAddress::from(ScratchSpace::start() + 1); + let new_vector_pointer_return = MemoryAddress::from(ScratchSpace::start() + 2); + let write_pointer_return = MemoryAddress::from(ScratchSpace::start() + 3); + + brillig_context.set_allocated_registers(vec![ + source_vector_pointer_arg, + item_push_count_arg, + new_vector_pointer_return, + write_pointer_return, + ]); + + let source_vector = BrilligVector { pointer: source_vector_pointer_arg }; + let target_vector = BrilligVector { pointer: new_vector_pointer_return }; + + // First we need to allocate the target vector incrementing the size by item_push_count_arg + let source_size = brillig_context.codegen_make_vector_length(source_vector); + + let target_size = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + brillig_context.memory_op_instruction( + source_size.address, + item_push_count_arg, + target_size.address, + BrilligBinaryOp::Add, + ); + + brillig_context.codegen_initialize_vector(target_vector, target_size); + + // Now we copy the source vector into the target vector + let source_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(source_vector); + let target_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(target_vector); + + if push_back { + brillig_context.codegen_mem_copy( + source_vector_items_pointer, + target_vector_items_pointer, + source_size, + ); + + brillig_context.memory_op_instruction( + target_vector_items_pointer, + source_size.address, + write_pointer_return, + BrilligBinaryOp::Add, + ); + } else { + brillig_context.mov_instruction(write_pointer_return, target_vector_items_pointer); + + brillig_context.memory_op_instruction( + target_vector_items_pointer, + item_push_count_arg, + target_vector_items_pointer, + BrilligBinaryOp::Add, + ); + + brillig_context.codegen_mem_copy( + source_vector_items_pointer, + target_vector_items_pointer, + source_size, + ); + } + + brillig_context.deallocate_single_addr(source_size); + brillig_context.deallocate_single_addr(target_size); + brillig_context.deallocate_register(source_vector_items_pointer); + brillig_context.deallocate_register(target_vector_items_pointer); +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop.rs new file mode 100644 index 00000000000..bb14ffac6be --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_pop.rs @@ -0,0 +1,113 @@ +use std::vec; + +use acvm::{acir::brillig::MemoryAddress, AcirField}; + +use super::ProcedureId; +use crate::brillig::brillig_ir::{ + brillig_variable::{BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, + registers::{RegisterAllocator, ScratchSpace}, + BrilligBinaryOp, BrilligContext, +}; + +impl BrilligContext { + /// Pops items from the vector, returning the new vector and the pointer to the popped items in read_pointer. + pub(crate) fn call_vector_pop_procedure( + &mut self, + source_vector: BrilligVector, + destination_vector: BrilligVector, + read_pointer: MemoryAddress, + item_pop_count: usize, + back: bool, + ) { + let source_vector_pointer_arg = MemoryAddress::from(ScratchSpace::start()); + let item_pop_count_arg = MemoryAddress::from(ScratchSpace::start() + 1); + let new_vector_pointer_return = MemoryAddress::from(ScratchSpace::start() + 2); + let read_pointer_return = MemoryAddress::from(ScratchSpace::start() + 3); + + self.mov_instruction(source_vector_pointer_arg, source_vector.pointer); + self.usize_const_instruction(item_pop_count_arg, item_pop_count.into()); + + self.add_procedure_call_instruction(ProcedureId::VectorPop(back)); + + self.mov_instruction(destination_vector.pointer, new_vector_pointer_return); + self.mov_instruction(read_pointer, read_pointer_return); + } +} + +pub(super) fn compile_vector_pop_procedure( + brillig_context: &mut BrilligContext, + pop_back: bool, +) { + let source_vector_pointer_arg = MemoryAddress::from(ScratchSpace::start()); + let item_pop_count_arg = MemoryAddress::from(ScratchSpace::start() + 1); + let new_vector_pointer_return = MemoryAddress::from(ScratchSpace::start() + 2); + let read_pointer_return = MemoryAddress::from(ScratchSpace::start() + 3); + + brillig_context.set_allocated_registers(vec![ + source_vector_pointer_arg, + item_pop_count_arg, + new_vector_pointer_return, + read_pointer_return, + ]); + + let source_vector = BrilligVector { pointer: source_vector_pointer_arg }; + let target_vector = BrilligVector { pointer: new_vector_pointer_return }; + + // First we need to allocate the target vector decrementing the size by removed_items.len() + let source_size = brillig_context.codegen_make_vector_length(source_vector); + + let target_size = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + brillig_context.memory_op_instruction( + source_size.address, + item_pop_count_arg, + target_size.address, + BrilligBinaryOp::Sub, + ); + + brillig_context.codegen_initialize_vector(target_vector, target_size); + + // Now we offset the source pointer by removed_items.len() + let source_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(source_vector); + let target_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(target_vector); + + if pop_back { + // Now we copy the source vector starting at index 0 into the target vector + brillig_context.codegen_mem_copy( + source_vector_items_pointer, + target_vector_items_pointer, + target_size, + ); + brillig_context.memory_op_instruction( + source_vector_items_pointer, + target_size.address, + read_pointer_return, + BrilligBinaryOp::Add, + ); + } else { + let source_copy_pointer = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + source_vector_items_pointer, + item_pop_count_arg, + source_copy_pointer, + BrilligBinaryOp::Add, + ); + + // Now we copy the source vector starting at index removed_items.len() into the target vector + brillig_context.codegen_mem_copy( + source_copy_pointer, + target_vector_items_pointer, + target_size, + ); + brillig_context.mov_instruction(read_pointer_return, source_vector_items_pointer); + + brillig_context.deallocate_register(source_copy_pointer); + } + + brillig_context.deallocate_single_addr(source_size); + brillig_context.deallocate_single_addr(target_size); + brillig_context.deallocate_register(source_vector_items_pointer); + brillig_context.deallocate_register(target_vector_items_pointer); +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_remove.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_remove.rs new file mode 100644 index 00000000000..d4a7217677f --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/vector_remove.rs @@ -0,0 +1,134 @@ +use std::vec; + +use acvm::{acir::brillig::MemoryAddress, AcirField}; + +use super::ProcedureId; +use crate::brillig::brillig_ir::{ + brillig_variable::{BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, + registers::{RegisterAllocator, ScratchSpace}, + BrilligBinaryOp, BrilligContext, +}; + +impl BrilligContext { + /// Removes items from the vector, returning the new vector. + pub(crate) fn call_vector_remove_procedure( + &mut self, + source_vector: BrilligVector, + destination_vector: BrilligVector, + index: SingleAddrVariable, + item_count: usize, + ) { + let source_vector_pointer_arg = MemoryAddress::from(ScratchSpace::start()); + let index_arg = MemoryAddress::from(ScratchSpace::start() + 1); + let item_count_arg = MemoryAddress::from(ScratchSpace::start() + 2); + let new_vector_pointer_return = MemoryAddress::from(ScratchSpace::start() + 3); + + self.mov_instruction(source_vector_pointer_arg, source_vector.pointer); + self.mov_instruction(index_arg, index.address); + self.usize_const_instruction(item_count_arg, item_count.into()); + + self.add_procedure_call_instruction(ProcedureId::VectorRemove); + + self.mov_instruction(destination_vector.pointer, new_vector_pointer_return); + } +} + +pub(super) fn compile_vector_remove_procedure( + brillig_context: &mut BrilligContext, +) { + let source_vector_pointer_arg = MemoryAddress::from(ScratchSpace::start()); + let index_arg = MemoryAddress::from(ScratchSpace::start() + 1); + let item_count_arg = MemoryAddress::from(ScratchSpace::start() + 2); + let new_vector_pointer_return = MemoryAddress::from(ScratchSpace::start() + 3); + + brillig_context.set_allocated_registers(vec![ + source_vector_pointer_arg, + index_arg, + item_count_arg, + new_vector_pointer_return, + ]); + + let source_vector = BrilligVector { pointer: source_vector_pointer_arg }; + let target_vector = BrilligVector { pointer: new_vector_pointer_return }; + let index = SingleAddrVariable::new_usize(index_arg); + + // First we need to allocate the target vector decrementing the size by removed_items.len() + let source_size = brillig_context.codegen_make_vector_length(source_vector); + + let target_size = SingleAddrVariable::new_usize(brillig_context.allocate_register()); + brillig_context.memory_op_instruction( + source_size.address, + item_count_arg, + target_size.address, + BrilligBinaryOp::Sub, + ); + + brillig_context.codegen_initialize_vector(target_vector, target_size); + + // Copy the elements to the left of the index + let source_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(source_vector); + let target_vector_items_pointer = + brillig_context.codegen_make_vector_items_pointer(target_vector); + + brillig_context.codegen_mem_copy( + source_vector_items_pointer, + target_vector_items_pointer, + index, + ); + + // Compute the source pointer after the removed items + let source_pointer_after_index = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + source_vector_items_pointer, + index.address, + source_pointer_after_index, + BrilligBinaryOp::Add, + ); + brillig_context.memory_op_instruction( + source_pointer_after_index, + item_count_arg, + source_pointer_after_index, + BrilligBinaryOp::Add, + ); + + // Compute the target pointer at the index + let target_pointer_at_index = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + target_vector_items_pointer, + index.address, + target_pointer_at_index, + BrilligBinaryOp::Add, + ); + + // Compute the number of elements to the right of the index + let item_count = brillig_context.allocate_register(); + brillig_context.memory_op_instruction( + source_size.address, + index.address, + item_count, + BrilligBinaryOp::Sub, + ); + brillig_context.memory_op_instruction( + item_count, + item_count_arg, + item_count, + BrilligBinaryOp::Sub, + ); + + // Copy the elements to the right of the index + brillig_context.codegen_mem_copy( + source_pointer_after_index, + target_pointer_at_index, + SingleAddrVariable::new_usize(item_count), + ); + + brillig_context.deallocate_register(source_pointer_after_index); + brillig_context.deallocate_register(target_pointer_at_index); + brillig_context.deallocate_register(item_count); + brillig_context.deallocate_single_addr(source_size); + brillig_context.deallocate_single_addr(target_size); + brillig_context.deallocate_register(source_vector_items_pointer); + brillig_context.deallocate_register(target_vector_items_pointer); +} diff --git a/compiler/noirc_evaluator/src/errors.rs b/compiler/noirc_evaluator/src/errors.rs index bcd6865b721..c4ba08f9acd 100644 --- a/compiler/noirc_evaluator/src/errors.rs +++ b/compiler/noirc_evaluator/src/errors.rs @@ -34,6 +34,13 @@ pub enum RuntimeError { UnInitialized { name: String, call_stack: CallStack }, #[error("Integer sized {num_bits:?} is over the max supported size of {max_num_bits:?}")] UnsupportedIntegerSize { num_bits: u32, max_num_bits: u32, call_stack: CallStack }, + #[error("Integer {value}, sized {num_bits:?}, is over the max supported size of {max_num_bits:?} for the blackbox function's inputs")] + InvalidBlackBoxInputBitSize { + value: String, + num_bits: u32, + max_num_bits: u32, + call_stack: CallStack, + }, #[error("Could not determine loop bound at compile-time")] UnknownLoopBound { call_stack: CallStack }, #[error("Argument is not constant")] @@ -156,6 +163,7 @@ impl RuntimeError { | RuntimeError::StaticAssertFailed { call_stack } | RuntimeError::IntegerOutOfBounds { call_stack, .. } | RuntimeError::UnsupportedIntegerSize { call_stack, .. } + | RuntimeError::InvalidBlackBoxInputBitSize { call_stack, .. } | RuntimeError::NestedSlice { call_stack, .. } | RuntimeError::BigIntModulus { call_stack, .. } | RuntimeError::UnconstrainedSliceReturnToConstrained { call_stack } diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index d12d49784ec..9586d08e10c 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1420,7 +1420,7 @@ impl AcirContext { } BlackBoxFunc::AES128Encrypt => { let invalid_input = "aes128_encrypt - operation requires a plaintext to encrypt"; - let input_size = match inputs.first().expect(invalid_input) { + let input_size: usize = match inputs.first().expect(invalid_input) { AcirValue::Array(values) => Ok::(values.len()), AcirValue::DynamicArray(dyn_array) => Ok::(dyn_array.len), _ => { @@ -1510,7 +1510,18 @@ impl AcirContext { let num_bits = typ.bit_size::(); match self.vars[&input].as_constant() { Some(constant) if allow_constant_inputs => { - single_val_witnesses.push(FunctionInput::constant(*constant, num_bits)); + single_val_witnesses.push( + FunctionInput::constant(*constant, num_bits).map_err( + |invalid_input_bit_size| { + RuntimeError::InvalidBlackBoxInputBitSize { + value: invalid_input_bit_size.value, + num_bits: invalid_input_bit_size.value_num_bits, + max_num_bits: invalid_input_bit_size.max_bits, + call_stack: self.get_call_stack(), + } + }, + )?, + ); } _ => { let witness_var = self.get_or_create_witness_var(input)?; diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 5091854a2ed..15b44fde65d 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -960,7 +960,6 @@ impl<'a> Context<'a> { arguments, BrilligFunctionContext::return_values(func), func.id(), - false, ); entry_point.name = func.name().to_string(); diff --git a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index 8c128c452d0..13e1e181dec 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -117,10 +117,6 @@ struct PerFunctionContext<'f> { /// Track a value's last load across all blocks. /// If a value is not used in anymore loads we can remove the last store to that value. last_loads: HashMap, - - /// Track whether the last instruction is an inc_rc/dec_rc instruction. - /// If it is we should not remove any known store values. - inside_rc_reload: bool, } impl<'f> PerFunctionContext<'f> { @@ -135,7 +131,6 @@ impl<'f> PerFunctionContext<'f> { blocks: BTreeMap::new(), instructions_to_remove: BTreeSet::new(), last_loads: HashMap::default(), - inside_rc_reload: false, } } @@ -324,7 +319,7 @@ impl<'f> PerFunctionContext<'f> { let known_value = references.get_known_value(value); if let Some(known_value) = known_value { let known_value_is_address = known_value == address; - if known_value_is_address && !self.inside_rc_reload { + if known_value_is_address { self.instructions_to_remove.insert(instruction); } } @@ -383,18 +378,6 @@ impl<'f> PerFunctionContext<'f> { Instruction::Call { arguments, .. } => self.mark_all_unknown(arguments, references), _ => (), } - - self.track_rc_reload_state(instruction); - } - - fn track_rc_reload_state(&mut self, instruction: InstructionId) { - match &self.inserter.function.dfg[instruction] { - // We just had an increment or decrement to an array's reference counter - Instruction::IncrementRc { .. } | Instruction::DecrementRc { .. } => { - self.inside_rc_reload = true; - } - _ => self.inside_rc_reload = false, - } } fn check_array_aliasing(&self, references: &mut Block, array: ValueId) { diff --git a/compiler/noirc_frontend/src/ast/traits.rs b/compiler/noirc_frontend/src/ast/traits.rs index 0463a5b8392..0de1dbaa021 100644 --- a/compiler/noirc_frontend/src/ast/traits.rs +++ b/compiler/noirc_frontend/src/ast/traits.rs @@ -95,7 +95,13 @@ pub struct TraitBound { } #[derive(Clone, Debug)] -pub enum TraitImplItem { +pub struct TraitImplItem { + pub kind: TraitImplItemKind, + pub span: Span, +} + +#[derive(Clone, Debug)] +pub enum TraitImplItemKind { Function(NoirFunction), Constant(Ident, UnresolvedType, Expression), Type { name: Ident, alias: UnresolvedType }, @@ -202,11 +208,17 @@ impl Display for NoirTraitImpl { } impl Display for TraitImplItem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.kind.fmt(f) + } +} + +impl Display for TraitImplItemKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - TraitImplItem::Function(function) => function.fmt(f), - TraitImplItem::Type { name, alias } => write!(f, "type {name} = {alias};"), - TraitImplItem::Constant(name, typ, value) => { + TraitImplItemKind::Function(function) => function.fmt(f), + TraitImplItemKind::Type { name, alias } => write!(f, "type {name} = {alias};"), + TraitImplItemKind::Constant(name, typ, value) => { write!(f, "let {name}: {typ} = {value};") } } diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index fcb4e4c5dd1..47083a5043b 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -22,8 +22,8 @@ use crate::{ use super::{ FunctionReturnType, GenericTypeArgs, IntegerBitSize, ItemVisibility, Pattern, Signedness, - UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, - UnresolvedTypeExpression, + TraitImplItemKind, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, + UnresolvedTypeData, UnresolvedTypeExpression, }; #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -69,6 +69,10 @@ pub trait Visitor { true } + fn visit_trait_impl_item_kind(&mut self, _: &TraitImplItemKind, _span: Span) -> bool { + true + } + fn visit_trait_impl_item_function(&mut self, _: &NoirFunction, _span: Span) -> bool { true } @@ -78,11 +82,17 @@ pub trait Visitor { _name: &Ident, _typ: &UnresolvedType, _expression: &Expression, + _span: Span, ) -> bool { true } - fn visit_trait_impl_item_type(&mut self, _name: &Ident, _alias: &UnresolvedType) -> bool { + fn visit_trait_impl_item_type( + &mut self, + _name: &Ident, + _alias: &UnresolvedType, + _span: Span, + ) -> bool { true } @@ -569,24 +579,32 @@ impl TraitImplItem { } pub fn accept_children(&self, visitor: &mut impl Visitor) { - match self { - TraitImplItem::Function(noir_function) => { - let span = Span::from( - noir_function.name_ident().span().start()..noir_function.span().end(), - ); + self.kind.accept(self.span, visitor); + } +} + +impl TraitImplItemKind { + pub fn accept(&self, span: Span, visitor: &mut impl Visitor) { + if visitor.visit_trait_impl_item_kind(self, span) { + self.accept_children(span, visitor); + } + } + pub fn accept_children(&self, span: Span, visitor: &mut impl Visitor) { + match self { + TraitImplItemKind::Function(noir_function) => { if visitor.visit_trait_impl_item_function(noir_function, span) { noir_function.accept(span, visitor); } } - TraitImplItem::Constant(name, unresolved_type, expression) => { - if visitor.visit_trait_impl_item_constant(name, unresolved_type, expression) { + TraitImplItemKind::Constant(name, unresolved_type, expression) => { + if visitor.visit_trait_impl_item_constant(name, unresolved_type, expression, span) { unresolved_type.accept(visitor); expression.accept(visitor); } } - TraitImplItem::Type { name, alias } => { - if visitor.visit_trait_impl_item_type(name, alias) { + TraitImplItemKind::Type { name, alias } => { + if visitor.visit_trait_impl_item_type(name, alias, span) { alias.accept(visitor); } } diff --git a/compiler/noirc_frontend/src/elaborator/statements.rs b/compiler/noirc_frontend/src/elaborator/statements.rs index 9e29978a9d5..543cf20b647 100644 --- a/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/compiler/noirc_frontend/src/elaborator/statements.rs @@ -249,6 +249,13 @@ impl<'context> Elaborator<'context> { } else { if let Some(definition) = self.interner.try_definition(ident.id) { mutable = definition.mutable; + + if definition.comptime && !self.in_comptime_context() { + self.push_err(ResolverError::MutatingComptimeInNonComptimeContext { + name: definition.name.clone(), + span: ident.location.span, + }); + } } let typ = self.interner.definition_type(ident.id).instantiate(self.interner).0; diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index 166c6479b15..9d1349b5209 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -1,7 +1,4 @@ -use std::{ - hash::{Hash, Hasher}, - rc::Rc, -}; +use std::rc::Rc; use acvm::{AcirField, FieldElement}; use builtin_helpers::{ @@ -43,7 +40,7 @@ use crate::{ Kind, QuotedType, ResolvedGeneric, Shared, Type, TypeVariable, }; -use self::builtin_helpers::{get_array, get_str, get_u8}; +use self::builtin_helpers::{eq_item, get_array, get_str, get_u8, hash_item}; use super::Interpreter; pub(crate) mod builtin_helpers; @@ -104,9 +101,11 @@ impl<'local, 'context> Interpreter<'local, 'context> { "fresh_type_variable" => fresh_type_variable(interner), "function_def_add_attribute" => function_def_add_attribute(self, arguments, location), "function_def_body" => function_def_body(interner, arguments, location), + "function_def_eq" => function_def_eq(arguments, location), "function_def_has_named_attribute" => { function_def_has_named_attribute(interner, arguments, location) } + "function_def_hash" => function_def_hash(arguments, location), "function_def_is_unconstrained" => { function_def_is_unconstrained(interner, arguments, location) } @@ -126,20 +125,24 @@ impl<'local, 'context> Interpreter<'local, 'context> { function_def_set_unconstrained(self, arguments, location) } "module_add_item" => module_add_item(self, arguments, location), + "module_eq" => module_eq(arguments, location), "module_functions" => module_functions(self, arguments, location), "module_has_named_attribute" => module_has_named_attribute(self, arguments, location), + "module_hash" => module_hash(arguments, location), "module_is_contract" => module_is_contract(self, arguments, location), "module_name" => module_name(interner, arguments, location), - "modulus_be_bits" => modulus_be_bits(interner, arguments, location), - "modulus_be_bytes" => modulus_be_bytes(interner, arguments, location), - "modulus_le_bits" => modulus_le_bits(interner, arguments, location), - "modulus_le_bytes" => modulus_le_bytes(interner, arguments, location), - "modulus_num_bits" => modulus_num_bits(interner, arguments, location), + "module_structs" => module_structs(self, arguments, location), + "modulus_be_bits" => modulus_be_bits(arguments, location), + "modulus_be_bytes" => modulus_be_bytes(arguments, location), + "modulus_le_bits" => modulus_le_bits(arguments, location), + "modulus_le_bytes" => modulus_le_bytes(arguments, location), + "modulus_num_bits" => modulus_num_bits(arguments, location), "quoted_as_expr" => quoted_as_expr(arguments, return_type, location), "quoted_as_module" => quoted_as_module(self, arguments, return_type, location), "quoted_as_trait_constraint" => quoted_as_trait_constraint(self, arguments, location), "quoted_as_type" => quoted_as_type(self, arguments, location), "quoted_eq" => quoted_eq(arguments, location), + "quoted_hash" => quoted_hash(arguments, location), "quoted_tokens" => quoted_tokens(arguments, location), "slice_insert" => slice_insert(interner, arguments, location), "slice_pop_back" => slice_pop_back(interner, arguments, location, call_stack), @@ -151,22 +154,24 @@ impl<'local, 'context> Interpreter<'local, 'context> { "struct_def_add_attribute" => struct_def_add_attribute(interner, arguments, location), "struct_def_add_generic" => struct_def_add_generic(interner, arguments, location), "struct_def_as_type" => struct_def_as_type(interner, arguments, location), + "struct_def_eq" => struct_def_eq(arguments, location), "struct_def_fields" => struct_def_fields(interner, arguments, location), "struct_def_generics" => struct_def_generics(interner, arguments, location), "struct_def_has_named_attribute" => { struct_def_has_named_attribute(interner, arguments, location) } + "struct_def_hash" => struct_def_hash(arguments, location), "struct_def_module" => struct_def_module(self, arguments, location), "struct_def_name" => struct_def_name(interner, arguments, location), "struct_def_set_fields" => struct_def_set_fields(interner, arguments, location), "to_le_radix" => to_le_radix(arguments, return_type, location), - "trait_constraint_eq" => trait_constraint_eq(interner, arguments, location), - "trait_constraint_hash" => trait_constraint_hash(interner, arguments, location), + "trait_constraint_eq" => trait_constraint_eq(arguments, location), + "trait_constraint_hash" => trait_constraint_hash(arguments, location), "trait_def_as_trait_constraint" => { trait_def_as_trait_constraint(interner, arguments, location) } - "trait_def_eq" => trait_def_eq(interner, arguments, location), - "trait_def_hash" => trait_def_hash(interner, arguments, location), + "trait_def_eq" => trait_def_eq(arguments, location), + "trait_def_hash" => trait_def_hash(arguments, location), "trait_impl_methods" => trait_impl_methods(interner, arguments, location), "trait_impl_trait_generic_args" => { trait_impl_trait_generic_args(interner, arguments, location) @@ -182,6 +187,7 @@ impl<'local, 'context> Interpreter<'local, 'context> { "type_get_trait_impl" => { type_get_trait_impl(interner, arguments, return_type, location) } + "type_hash" => type_hash(arguments, location), "type_implements" => type_implements(interner, arguments, location), "type_is_bool" => type_is_bool(arguments, location), "type_is_field" => type_is_field(arguments, location), @@ -427,7 +433,15 @@ fn struct_def_generics( Ok(Value::Slice(generics.collect(), typ)) } -// fn has_named_attribute(self, name: Quoted) -> bool +fn struct_def_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + hash_item(arguments, location, get_struct) +} + +fn struct_def_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + eq_item(arguments, location, get_struct) +} + +// fn has_named_attribute(self, name: str) -> bool {} fn struct_def_has_named_attribute( interner: &NodeInterner, arguments: Vec<(Value, Location)>, @@ -436,14 +450,9 @@ fn struct_def_has_named_attribute( let (self_argument, name) = check_two_arguments(arguments, location)?; let struct_id = get_struct(self_argument)?; - let name = get_quoted(name)?; - let name = name.iter().map(|token| token.to_string()).collect::>().join(""); + let name = get_str(interner, name)?; - let attributes = interner.struct_attributes(&struct_id); - let attributes = attributes.iter().filter_map(|attribute| attribute.as_custom()); - let attributes = attributes.map(|attribute| &attribute.contents); - - Ok(Value::Bool(has_named_attribute(&name, attributes, location))) + Ok(Value::Bool(has_named_attribute(&name, interner.struct_attributes(&struct_id)))) } /// fn fields(self) -> [(Quoted, Type)] @@ -903,12 +912,12 @@ where // fn type_eq(_first: Type, _second: Type) -> bool fn type_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult { - let (self_type, other_type) = check_two_arguments(arguments, location)?; - - let self_type = get_type(self_type)?; - let other_type = get_type(other_type)?; + eq_item(arguments, location, get_type) +} - Ok(Value::Bool(self_type == other_type)) +// fn type_hash(_t: Type) -> Field +fn type_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + hash_item(arguments, location, get_type) } // fn get_trait_impl(self, constraint: TraitConstraint) -> Option @@ -977,65 +986,23 @@ fn type_of(arguments: Vec<(Value, Location)>, location: Location) -> IResult Field -fn trait_constraint_hash( - _interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let argument = check_one_argument(arguments, location)?; - - let bound = get_trait_constraint(argument)?; - - let mut hasher = std::collections::hash_map::DefaultHasher::new(); - bound.hash(&mut hasher); - let hash = hasher.finish(); - - Ok(Value::Field((hash as u128).into())) +fn trait_constraint_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + hash_item(arguments, location, get_trait_constraint) } // fn constraint_eq(constraint_a: TraitConstraint, constraint_b: TraitConstraint) -> bool -fn trait_constraint_eq( - _interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let (value_a, value_b) = check_two_arguments(arguments, location)?; - - let constraint_a = get_trait_constraint(value_a)?; - let constraint_b = get_trait_constraint(value_b)?; - - Ok(Value::Bool(constraint_a == constraint_b)) +fn trait_constraint_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + eq_item(arguments, location, get_trait_constraint) } // fn trait_def_hash(def: TraitDefinition) -> Field -fn trait_def_hash( - _interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let argument = check_one_argument(arguments, location)?; - - let id = get_trait_def(argument)?; - - let mut hasher = std::collections::hash_map::DefaultHasher::new(); - id.hash(&mut hasher); - let hash = hasher.finish(); - - Ok(Value::Field((hash as u128).into())) +fn trait_def_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + hash_item(arguments, location, get_trait_def) } // fn trait_def_eq(def_a: TraitDefinition, def_b: TraitDefinition) -> bool -fn trait_def_eq( - _interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let (id_a, id_b) = check_two_arguments(arguments, location)?; - - let id_a = get_trait_def(id_a)?; - let id_b = get_trait_def(id_b)?; - - Ok(Value::Bool(id_a == id_b)) +fn trait_def_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + eq_item(arguments, location, get_trait_def) } // fn methods(self) -> [FunctionDefinition] @@ -1985,7 +1952,7 @@ fn function_def_body( } } -// fn has_named_attribute(self, name: Quoted) -> bool +// fn has_named_attribute(self, name: str) -> bool {} fn function_def_has_named_attribute( interner: &NodeInterner, arguments: Vec<(Value, Location)>, @@ -1993,15 +1960,25 @@ fn function_def_has_named_attribute( ) -> IResult { let (self_argument, name) = check_two_arguments(arguments, location)?; let func_id = get_function_def(self_argument)?; - let func_meta = interner.function_meta(&func_id); - let name = get_quoted(name)?; - let name = name.iter().map(|token| token.to_string()).collect::>().join(""); + let name = &*get_str(interner, name)?; + + let modifiers = interner.function_modifiers(&func_id); + if let Some(attribute) = &modifiers.attributes.function { + if name == attribute.name() { + return Ok(Value::Bool(true)); + } + } + + Ok(Value::Bool(has_named_attribute(name, &modifiers.attributes.secondary))) +} - let attributes = &func_meta.custom_attributes; - let attributes = attributes.iter().map(|attribute| &attribute.contents); +fn function_def_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + hash_item(arguments, location, get_function_def) +} - Ok(Value::Bool(has_named_attribute(&name, attributes, location))) +fn function_def_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + eq_item(arguments, location, get_function_def) } // fn is_unconstrained(self) -> bool @@ -2270,6 +2247,14 @@ fn module_add_item( Ok(Value::Unit) } +fn module_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + hash_item(arguments, location, get_module) +} + +fn module_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + eq_item(arguments, location, get_module) +} + // fn functions(self) -> [FunctionDefinition] fn module_functions( interpreter: &Interpreter, @@ -2294,7 +2279,31 @@ fn module_functions( Ok(Value::Slice(func_ids, slice_type)) } -// fn has_named_attribute(self, name: Quoted) -> bool +// fn structs(self) -> [StructDefinition] +fn module_structs( + interpreter: &Interpreter, + arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + let self_argument = check_one_argument(arguments, location)?; + let module_id = get_module(self_argument)?; + let module_data = interpreter.elaborator.get_module(module_id); + let struct_ids = module_data + .type_definitions() + .filter_map(|module_def_id| { + if let ModuleDefId::TypeId(id) = module_def_id { + Some(Value::StructDefinition(id)) + } else { + None + } + }) + .collect(); + + let slice_type = Type::Slice(Box::new(Type::Quoted(QuotedType::StructDefinition))); + Ok(Value::Slice(struct_ids, slice_type)) +} + +// fn has_named_attribute(self, name: str) -> bool {} fn module_has_named_attribute( interpreter: &Interpreter, arguments: Vec<(Value, Location)>, @@ -2304,12 +2313,9 @@ fn module_has_named_attribute( let module_id = get_module(self_argument)?; let module_data = interpreter.elaborator.get_module(module_id); - let name = get_quoted(name)?; - let name = name.iter().map(|token| token.to_string()).collect::>().join(""); - - let attributes = module_data.outer_attributes.iter().chain(&module_data.inner_attributes); + let name = get_str(interpreter.elaborator.interner, name)?; - Ok(Value::Bool(has_named_attribute(&name, attributes, location))) + Ok(Value::Bool(has_named_attribute(&name, &module_data.attributes))) } // fn is_contract(self) -> bool @@ -2336,11 +2342,7 @@ fn module_name( Ok(Value::Quoted(tokens)) } -fn modulus_be_bits( - _interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { +fn modulus_be_bits(arguments: Vec<(Value, Location)>, location: Location) -> IResult { check_argument_count(0, &arguments, location)?; let bits = FieldElement::modulus().to_radix_be(2); @@ -2351,11 +2353,7 @@ fn modulus_be_bits( Ok(Value::Slice(bits_vector, typ)) } -fn modulus_be_bytes( - _interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { +fn modulus_be_bytes(arguments: Vec<(Value, Location)>, location: Location) -> IResult { check_argument_count(0, &arguments, location)?; let bytes = FieldElement::modulus().to_bytes_be(); @@ -2366,35 +2364,23 @@ fn modulus_be_bytes( Ok(Value::Slice(bytes_vector, typ)) } -fn modulus_le_bits( - interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let Value::Slice(bits, typ) = modulus_be_bits(interner, arguments, location)? else { +fn modulus_le_bits(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + let Value::Slice(bits, typ) = modulus_be_bits(arguments, location)? else { unreachable!("modulus_be_bits must return slice") }; let reversed_bits = bits.into_iter().rev().collect(); Ok(Value::Slice(reversed_bits, typ)) } -fn modulus_le_bytes( - interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let Value::Slice(bytes, typ) = modulus_be_bytes(interner, arguments, location)? else { +fn modulus_le_bytes(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + let Value::Slice(bytes, typ) = modulus_be_bytes(arguments, location)? else { unreachable!("modulus_be_bytes must return slice") }; let reversed_bytes = bytes.into_iter().rev().collect(); Ok(Value::Slice(reversed_bytes, typ)) } -fn modulus_num_bits( - _interner: &mut NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { +fn modulus_num_bits(arguments: Vec<(Value, Location)>, location: Location) -> IResult { check_argument_count(0, &arguments, location)?; let bits = FieldElement::max_num_bits().into(); Ok(Value::U64(bits)) @@ -2402,19 +2388,18 @@ fn modulus_num_bits( // fn quoted_eq(_first: Quoted, _second: Quoted) -> bool fn quoted_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult { - let (self_value, other_value) = check_two_arguments(arguments, location)?; - - let self_quoted = get_quoted(self_value)?; - let other_quoted = get_quoted(other_value)?; + eq_item(arguments, location, get_quoted) +} - Ok(Value::Bool(self_quoted == other_quoted)) +fn quoted_hash(arguments: Vec<(Value, Location)>, location: Location) -> IResult { + hash_item(arguments, location, get_quoted) } fn trait_def_as_trait_constraint( interner: &mut NodeInterner, arguments: Vec<(Value, Location)>, location: Location, -) -> Result { +) -> IResult { let argument = check_one_argument(arguments, location)?; let trait_id = get_trait_def(argument)?; diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs index 6e72866bec0..911e89a52ec 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin/builtin_helpers.rs @@ -1,4 +1,5 @@ -use std::rc::Rc; +use std::hash::Hash; +use std::{hash::Hasher, rc::Rc}; use acvm::FieldElement; use noirc_errors::Location; @@ -8,7 +9,6 @@ use crate::{ BlockExpression, ExpressionKind, IntegerBitSize, LValue, Pattern, Signedness, StatementKind, UnresolvedTypeData, }, - elaborator::Elaborator, hir::{ comptime::{ errors::IResult, @@ -25,7 +25,7 @@ use crate::{ macros_api::{NodeInterner, StructId}, node_interner::{FuncId, TraitId, TraitImplId}, parser::NoirParser, - token::{Token, Tokens}, + token::{SecondaryAttribute, Token, Tokens}, QuotedType, Type, }; @@ -449,25 +449,39 @@ pub(super) fn block_expression_to_value(block_expr: BlockExpression) -> Value { Value::Slice(statements, typ) } -pub(super) fn has_named_attribute<'a>( - name: &'a str, - attributes: impl Iterator, - location: Location, -) -> bool { +pub(super) fn has_named_attribute(name: &str, attributes: &[SecondaryAttribute]) -> bool { for attribute in attributes { - let parse_result = Elaborator::parse_attribute(attribute, location); - let Ok(Some((function, _arguments))) = parse_result else { - continue; - }; - - let ExpressionKind::Variable(path) = function.kind else { - continue; - }; - - if path.last_name() == name { - return true; + if let Some(attribute_name) = attribute.name() { + if name == attribute_name { + return true; + } } } false } + +pub(super) fn hash_item( + arguments: Vec<(Value, Location)>, + location: Location, + get_item: impl FnOnce((Value, Location)) -> IResult, +) -> IResult { + let argument = check_one_argument(arguments, location)?; + let item = get_item(argument)?; + + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + item.hash(&mut hasher); + let hash = hasher.finish(); + Ok(Value::Field((hash as u128).into())) +} + +pub(super) fn eq_item( + arguments: Vec<(Value, Location)>, + location: Location, + mut get_item: impl FnMut((Value, Location)) -> IResult, +) -> IResult { + let (self_arg, other_arg) = check_two_arguments(arguments, location)?; + let self_arg = get_item(self_arg)?; + let other_arg = get_item(other_arg)?; + Ok(Value::Bool(self_arg == other_arg)) +} diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index d93b708c91d..57c7fdd9cdb 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -12,7 +12,7 @@ use rustc_hash::FxHashMap as HashMap; use crate::ast::{ Documented, FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, - NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Pattern, TraitImplItem, + NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Pattern, TraitImplItemKind, TraitItem, TypeImpl, }; use crate::hir::resolution::errors::ResolverError; @@ -1124,18 +1124,18 @@ pub(crate) fn collect_trait_impl_items( let module = ModuleId { krate, local_id }; for item in std::mem::take(&mut trait_impl.items) { - match item.item { - TraitImplItem::Function(impl_method) => { + match item.item.kind { + TraitImplItemKind::Function(impl_method) => { let func_id = interner.push_empty_fn(); let location = Location::new(impl_method.span(), file_id); interner.push_function(func_id, &impl_method.def, module, location); interner.set_doc_comments(ReferenceId::Function(func_id), item.doc_comments); unresolved_functions.push_fn(local_id, func_id, impl_method); } - TraitImplItem::Constant(name, typ, expr) => { + TraitImplItemKind::Constant(name, typ, expr) => { associated_constants.push((name, typ, expr)); } - TraitImplItem::Type { name, alias } => { + TraitImplItemKind::Type { name, alias } => { associated_types.push((name, alias)); } } diff --git a/compiler/noirc_frontend/src/hir/def_map/module_data.rs b/compiler/noirc_frontend/src/hir/def_map/module_data.rs index e829df3572c..6a0f472ef75 100644 --- a/compiler/noirc_frontend/src/hir/def_map/module_data.rs +++ b/compiler/noirc_frontend/src/hir/def_map/module_data.rs @@ -26,8 +26,7 @@ pub struct ModuleData { /// True if this module is a `contract Foo { ... }` module containing contract functions pub is_contract: bool, - pub outer_attributes: Vec, - pub inner_attributes: Vec, + pub attributes: Vec, } impl ModuleData { @@ -38,11 +37,8 @@ impl ModuleData { inner_attributes: Vec, is_contract: bool, ) -> ModuleData { - let outer_attributes = outer_attributes.iter().filter_map(|attr| attr.as_custom()); - let outer_attributes = outer_attributes.map(|attr| attr.contents.to_string()).collect(); - - let inner_attributes = inner_attributes.iter().filter_map(|attr| attr.as_custom()); - let inner_attributes = inner_attributes.map(|attr| attr.contents.to_string()).collect(); + let mut attributes = outer_attributes; + attributes.extend(inner_attributes); ModuleData { parent, @@ -51,8 +47,7 @@ impl ModuleData { definitions: ItemScope::default(), location, is_contract, - outer_attributes, - inner_attributes, + attributes, } } diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index ec22c8f1986..cb726a01dec 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -128,6 +128,8 @@ pub enum ResolverError { QuoteInRuntimeCode { span: Span }, #[error("Comptime-only type `{typ}` cannot be used in runtime code")] ComptimeTypeInRuntimeCode { typ: String, span: Span }, + #[error("Comptime variable `{name}` cannot be mutated in a non-comptime context")] + MutatingComptimeInNonComptimeContext { name: String, span: Span }, } impl ResolverError { @@ -522,6 +524,13 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *span, ) }, + ResolverError::MutatingComptimeInNonComptimeContext { name, span } => { + Diagnostic::simple_error( + format!("Comptime variable `{name}` cannot be mutated in a non-comptime context"), + format!("`{name}` mutated here"), + *span, + ) + }, } } } diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 180d773ff8d..bcbcc8ad789 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1630,8 +1630,18 @@ impl Type { (InfixExpr(lhs_a, op_a, rhs_a), InfixExpr(lhs_b, op_b, rhs_b)) => { if op_a == op_b { - lhs_a.try_unify(lhs_b, bindings)?; - rhs_a.try_unify(rhs_b, bindings) + // We need to preserve the original bindings since if syntactic equality + // fails we fall back to other equality strategies. + let mut new_bindings = bindings.clone(); + let lhs_result = lhs_a.try_unify(lhs_b, &mut new_bindings); + let rhs_result = rhs_a.try_unify(rhs_b, &mut new_bindings); + + if lhs_result.is_ok() && rhs_result.is_ok() { + *bindings = new_bindings; + Ok(()) + } else { + lhs.try_unify_by_moving_constant_terms(&rhs, bindings) + } } else { Err(UnificationError) } diff --git a/compiler/noirc_frontend/src/hir_def/types/arithmetic.rs b/compiler/noirc_frontend/src/hir_def/types/arithmetic.rs index ad07185dff1..44a7526c894 100644 --- a/compiler/noirc_frontend/src/hir_def/types/arithmetic.rs +++ b/compiler/noirc_frontend/src/hir_def/types/arithmetic.rs @@ -1,6 +1,6 @@ use std::collections::BTreeSet; -use crate::{BinaryTypeOperator, Type}; +use crate::{BinaryTypeOperator, Type, TypeBindings, UnificationError}; impl Type { /// Try to canonicalize the representation of this type. @@ -212,4 +212,44 @@ impl Type { _ => None, } } + + /// Try to unify equations like `(..) + 3 = (..) + 1` + /// by transforming them to `(..) + 2 = (..)` + pub(super) fn try_unify_by_moving_constant_terms( + &self, + other: &Type, + bindings: &mut TypeBindings, + ) -> Result<(), UnificationError> { + if let Type::InfixExpr(lhs_a, op_a, rhs_a) = self { + if let Some(inverse) = op_a.inverse() { + if let Some(rhs_a) = rhs_a.evaluate_to_u32() { + let rhs_a = Box::new(Type::Constant(rhs_a)); + let new_other = Type::InfixExpr(Box::new(other.clone()), inverse, rhs_a); + + let mut tmp_bindings = bindings.clone(); + if lhs_a.try_unify(&new_other, &mut tmp_bindings).is_ok() { + *bindings = tmp_bindings; + return Ok(()); + } + } + } + } + + if let Type::InfixExpr(lhs_b, op_b, rhs_b) = other { + if let Some(inverse) = op_b.inverse() { + if let Some(rhs_b) = rhs_b.evaluate_to_u32() { + let rhs_b = Box::new(Type::Constant(rhs_b)); + let new_self = Type::InfixExpr(Box::new(self.clone()), inverse, rhs_b); + + let mut tmp_bindings = bindings.clone(); + if new_self.try_unify(lhs_b, &mut tmp_bindings).is_ok() { + *bindings = tmp_bindings; + return Ok(()); + } + } + } + } + + Err(UnificationError) + } } diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index f5f7f0458d7..012b21a8904 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -10,6 +10,8 @@ use crate::{ }, }; +use super::Lexer; + /// Represents a token in noir's grammar - a word, number, /// or symbol that can be used in noir's syntax. This is the /// smallest unit of grammar. A parser may (will) decide to parse @@ -362,11 +364,11 @@ impl fmt::Display for Token { Token::Ident(ref s) => write!(f, "{s}"), Token::Int(n) => write!(f, "{}", n.to_u128()), Token::Bool(b) => write!(f, "{b}"), - Token::Str(ref b) => write!(f, "{b}"), - Token::FmtStr(ref b) => write!(f, "f{b}"), + Token::Str(ref b) => write!(f, "{b:?}"), + Token::FmtStr(ref b) => write!(f, "f{b:?}"), Token::RawStr(ref b, hashes) => { let h: String = std::iter::once('#').cycle().take(hashes as usize).collect(); - write!(f, "r{h}\"{b}\"{h}") + write!(f, "r{h}{b:?}{h}") } Token::Keyword(k) => write!(f, "{k}"), Token::Attribute(ref a) => write!(f, "{a}"), @@ -868,6 +870,18 @@ impl FunctionAttribute { pub fn is_no_predicates(&self) -> bool { matches!(self, FunctionAttribute::NoPredicates) } + + pub fn name(&self) -> &'static str { + match self { + FunctionAttribute::Foreign(_) => "foreign", + FunctionAttribute::Builtin(_) => "builtin", + FunctionAttribute::Oracle(_) => "oracle", + FunctionAttribute::Test(_) => "test", + FunctionAttribute::Recursive => "recursive", + FunctionAttribute::Fold => "fold", + FunctionAttribute::NoPredicates => "no_predicates", + } + } } impl fmt::Display for FunctionAttribute { @@ -903,15 +917,6 @@ pub enum SecondaryAttribute { Varargs, } -#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] -pub struct CustomAtrribute { - pub contents: String, - // The span of the entire attribute, including leading `#[` and trailing `]` - pub span: Span, - // The span for the attribute contents (what's inside `#[...]`) - pub contents_span: Span, -} - impl SecondaryAttribute { pub(crate) fn as_custom(&self) -> Option<&CustomAtrribute> { if let Self::Custom(attribute) = self { @@ -920,6 +925,20 @@ impl SecondaryAttribute { None } } + + pub(crate) fn name(&self) -> Option { + match self { + SecondaryAttribute::Deprecated(_) => Some("deprecated".to_string()), + SecondaryAttribute::ContractLibraryMethod => { + Some("contract_library_method".to_string()) + } + SecondaryAttribute::Export => Some("export".to_string()), + SecondaryAttribute::Field(_) => Some("field".to_string()), + SecondaryAttribute::Custom(custom) => custom.name(), + SecondaryAttribute::Abi(_) => Some("abi".to_string()), + SecondaryAttribute::Varargs => Some("varargs".to_string()), + } + } } impl fmt::Display for SecondaryAttribute { @@ -939,6 +958,27 @@ impl fmt::Display for SecondaryAttribute { } } +#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] +pub struct CustomAtrribute { + pub contents: String, + // The span of the entire attribute, including leading `#[` and trailing `]` + pub span: Span, + // The span for the attribute contents (what's inside `#[...]`) + pub contents_span: Span, +} + +impl CustomAtrribute { + fn name(&self) -> Option { + let mut lexer = Lexer::new(&self.contents); + let token = lexer.next()?.ok()?; + if let Token::Ident(ident) = token.into_token() { + Some(ident) + } else { + None + } + } +} + impl AsRef for FunctionAttribute { fn as_ref(&self) -> &str { match self { diff --git a/compiler/noirc_frontend/src/parser/parser/traits.rs b/compiler/noirc_frontend/src/parser/parser/traits.rs index cb17bf2caf7..58db2465f22 100644 --- a/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -10,9 +10,10 @@ use super::{ use crate::ast::{ Documented, Expression, ItemVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, - TraitItem, UnresolvedTraitConstraint, UnresolvedType, + TraitImplItemKind, TraitItem, UnresolvedTraitConstraint, UnresolvedType, }; use crate::macros_api::Pattern; +use crate::parser::spanned; use crate::{ parser::{ ignore_then_commit, parenthesized, parser::primitives::keyword, NoirParser, ParserError, @@ -173,7 +174,7 @@ fn trait_implementation_body() -> impl NoirParser> } // Trait impl functions are always public f.def_mut().visibility = ItemVisibility::Public; - TraitImplItem::Function(f) + TraitImplItemKind::Function(f) }); let alias = keyword(Keyword::Type) @@ -181,11 +182,11 @@ fn trait_implementation_body() -> impl NoirParser> .then_ignore(just(Token::Assign)) .then(parse_type()) .then_ignore(just(Token::Semicolon)) - .map(|(name, alias)| TraitImplItem::Type { name, alias }); + .map(|(name, alias)| TraitImplItemKind::Type { name, alias }); let let_statement = let_statement(expression()).then_ignore(just(Token::Semicolon)).try_map( |((pattern, typ), expr), span| match pattern { - Pattern::Identifier(ident) => Ok(TraitImplItem::Constant(ident, typ, expr)), + Pattern::Identifier(ident) => Ok(TraitImplItemKind::Constant(ident, typ, expr)), _ => Err(ParserError::with_reason( ParserErrorReason::PatternInTraitFunctionParameter, span, @@ -195,7 +196,7 @@ fn trait_implementation_body() -> impl NoirParser> let item = choice((function, alias, let_statement)); outer_doc_comments() - .then(item) + .then(spanned(item).map(|(kind, span)| TraitImplItem { kind, span })) .map(|(doc_comments, item)| Documented::new(item, doc_comments)) .repeated() } diff --git a/compiler/wasm/scripts/install_wasm-pack.sh b/compiler/wasm/scripts/install_wasm-pack.sh index b0fdffe0458..8936dd86fb7 100755 --- a/compiler/wasm/scripts/install_wasm-pack.sh +++ b/compiler/wasm/scripts/install_wasm-pack.sh @@ -3,10 +3,7 @@ set -eu cd $(dirname "$0")/.. -# Install wasm-pack -CARGO_BINSTALL_CHECK=$(./scripts/command-check.sh cargo-binstall) -if [ $CARGO_BINSTALL_CHECK != "true" ]; then - curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash -fi +../../.github/scripts/cargo-binstall-install.sh +# Install wasm-pack cargo-binstall wasm-pack@0.12.1 -y --force diff --git a/cspell.json b/cspell.json index 293523d7c15..4d83c535e7d 100644 --- a/cspell.json +++ b/cspell.json @@ -25,6 +25,7 @@ "bindgen", "bitand", "bitmask", + "bitsize", "blackbox", "boilerplate", "boilerplates", diff --git a/docs/docs/noir/standard_library/meta/function_def.md b/docs/docs/noir/standard_library/meta/function_def.md index c9fa3b345f0..583771aeb73 100644 --- a/docs/docs/noir/standard_library/meta/function_def.md +++ b/docs/docs/noir/standard_library/meta/function_def.md @@ -101,3 +101,14 @@ This means any functions called at compile-time are invalid targets for this met Mutates the function to be unconstrained (if `true` is given) or not (if `false` is given). This is only valid on functions in the current crate which have not yet been resolved. This means any functions called at compile-time are invalid targets for this method. + +## Trait Implementations + +```rust +impl Eq for FunctionDefinition +impl Hash for FunctionDefinition +``` + +Note that each function is assigned a unique ID internally and this is what is used for +equality and hashing. So even functions with identical signatures and bodies may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/docs/noir/standard_library/meta/module.md b/docs/docs/noir/standard_library/meta/module.md index de042760d51..2765718dd7b 100644 --- a/docs/docs/noir/standard_library/meta/module.md +++ b/docs/docs/noir/standard_library/meta/module.md @@ -16,17 +16,11 @@ Adds a top-level item (a function, a struct, a global, etc.) to the module. Adding multiple items in one go is also valid if the `Quoted` value has multiple items in it. Note that the items are type-checked as if they are inside the module they are being added to. -### name - -#include_code name noir_stdlib/src/meta/module.nr rust - -Returns the name of the module. - ### functions #include_code functions noir_stdlib/src/meta/module.nr rust -Returns each function in the module. +Returns each function defined in the module. ### has_named_attribute @@ -39,3 +33,26 @@ Returns true if this module has a custom attribute with the given name. #include_code is_contract noir_stdlib/src/meta/module.nr rust `true` if this module is a contract module (was declared via `contract foo { ... }`). + +### name + +#include_code name noir_stdlib/src/meta/module.nr rust + +Returns the name of the module. + +### structs + +#include_code structs noir_stdlib/src/meta/module.nr rust + +Returns each struct defined in the module. + +## Trait Implementations + +```rust +impl Eq for Module +impl Hash for Module +``` + +Note that each module is assigned a unique ID internally and this is what is used for +equality and hashing. So even modules with identical names and contents may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/docs/noir/standard_library/meta/op.md b/docs/docs/noir/standard_library/meta/op.md index d8b154edc02..55d2d244344 100644 --- a/docs/docs/noir/standard_library/meta/op.md +++ b/docs/docs/noir/standard_library/meta/op.md @@ -43,6 +43,13 @@ Returns `true` if this operator is `-`. Returns this operator as a `Quoted` value. +### Trait Implementations + +```rust +impl Eq for UnaryOp +impl Hash for UnaryOp +``` + ### BinaryOp Represents a binary operator. One of `+`, `-`, `*`, `/`, `%`, `==`, `!=`, `<`, `<=`, `>`, `>=`, `&`, `|`, `^`, `>>`, or `<<`. @@ -143,4 +150,11 @@ Represents a binary operator. One of `+`, `-`, `*`, `/`, `%`, `==`, `!=`, `<`, ` #include_code binary_quoted noir_stdlib/src/meta/op.nr rust -Returns this operator as a `Quoted` value. \ No newline at end of file +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for BinaryOp +impl Hash for BinaryOp +``` diff --git a/docs/docs/noir/standard_library/meta/quoted.md b/docs/docs/noir/standard_library/meta/quoted.md index ac075d96648..11dacd51fcb 100644 --- a/docs/docs/noir/standard_library/meta/quoted.md +++ b/docs/docs/noir/standard_library/meta/quoted.md @@ -60,4 +60,5 @@ Returns a slice of the individual tokens that form this token stream. ```rust impl Eq for Quoted +impl Hash for Quoted ``` diff --git a/docs/docs/noir/standard_library/meta/struct_def.md b/docs/docs/noir/standard_library/meta/struct_def.md index c088e538fc9..535708e0353 100644 --- a/docs/docs/noir/standard_library/meta/struct_def.md +++ b/docs/docs/noir/standard_library/meta/struct_def.md @@ -117,3 +117,14 @@ comptime fn mangle_fields(s: StructDefinition) { ]); } ``` + +## Trait Implementations + +```rust +impl Eq for StructDefinition +impl Hash for StructDefinition +``` + +Note that each struct is assigned a unique ID internally and this is what is used for +equality and hashing. So even structs with identical generics and fields may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/docs/noir/standard_library/meta/typ.md b/docs/docs/noir/standard_library/meta/typ.md index 1334092a9fa..5a8b43b1dfa 100644 --- a/docs/docs/noir/standard_library/meta/typ.md +++ b/docs/docs/noir/standard_library/meta/typ.md @@ -150,7 +150,8 @@ fn foo() where T: Default { ```rust impl Eq for Type +impl Hash for Type ``` Note that this is syntactic equality, this is not the same as whether two types will type check to be the same type. Unless type inference or generics are being used however, users should not -typically have to worry about this distinction. +typically have to worry about this distinction unless `std::meta::typ::fresh_type_variable` is used. diff --git a/noir_stdlib/src/bigint.nr b/noir_stdlib/src/bigint.nr index 81dad968bf7..34eca47046d 100644 --- a/noir_stdlib/src/bigint.nr +++ b/noir_stdlib/src/bigint.nr @@ -56,19 +56,15 @@ struct Secpk1Fq { impl BigField for Secpk1Fq { fn from_le_bytes(bytes: [u8]) -> Secpk1Fq { assert(bytes.len() <= 32); - let mut array = [0;32]; + let mut array = [0; 32]; for i in 0..bytes.len() { array[i] = bytes[i]; } - Secpk1Fq { - array: array, - } + Secpk1Fq { array } } - fn from_le_bytes_32(bytes: [u8;32]) -> Secpk1Fq { - Secpk1Fq { - array: bytes, - } + fn from_le_bytes_32(bytes: [u8; 32]) -> Secpk1Fq { + Secpk1Fq { array: bytes } } fn to_le_bytes(self) -> [u8] { @@ -76,40 +72,32 @@ impl BigField for Secpk1Fq { } } -impl Add for Secpk1Fq { +impl Add for Secpk1Fq { fn add(self: Self, other: Secpk1Fq) -> Secpk1Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); - Secpk1Fq { - array: a.bigint_add(b).to_le_bytes() - } + Secpk1Fq { array: a.bigint_add(b).to_le_bytes() } } } -impl Sub for Secpk1Fq { +impl Sub for Secpk1Fq { fn sub(self: Self, other: Secpk1Fq) -> Secpk1Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); - Secpk1Fq { - array: a.bigint_sub(b).to_le_bytes() - } + Secpk1Fq { array: a.bigint_sub(b).to_le_bytes() } } } -impl Mul for Secpk1Fq { +impl Mul for Secpk1Fq { fn mul(self: Self, other: Secpk1Fq) -> Secpk1Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); - Secpk1Fq { - array: a.bigint_mul(b).to_le_bytes() - } + Secpk1Fq { array: a.bigint_mul(b).to_le_bytes() } } } -impl Div for Secpk1Fq { +impl Div for Secpk1Fq { fn div(self: Self, other: Secpk1Fq) -> Secpk1Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); - Secpk1Fq { - array: a.bigint_div(b).to_le_bytes() - } + Secpk1Fq { array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpk1Fq { @@ -125,60 +113,48 @@ struct Secpk1Fr { impl BigField for Secpk1Fr { fn from_le_bytes(bytes: [u8]) -> Secpk1Fr { assert(bytes.len() <= 32); - let mut array = [0;32]; + let mut array = [0; 32]; for i in 0..bytes.len() { array[i] = bytes[i]; } - Secpk1Fr { - array: array, - } + Secpk1Fr { array } } - fn from_le_bytes_32(bytes: [u8;32]) -> Secpk1Fr { - Secpk1Fr { - array: bytes, - } + fn from_le_bytes_32(bytes: [u8; 32]) -> Secpk1Fr { + Secpk1Fr { array: bytes } } - + fn to_le_bytes(self) -> [u8] { self.array } } -impl Add for Secpk1Fr { +impl Add for Secpk1Fr { fn add(self: Self, other: Secpk1Fr) -> Secpk1Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fr); - Secpk1Fr { - array: a.bigint_add(b).to_le_bytes() - } + Secpk1Fr { array: a.bigint_add(b).to_le_bytes() } } } -impl Sub for Secpk1Fr { +impl Sub for Secpk1Fr { fn sub(self: Self, other: Secpk1Fr) -> Secpk1Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fr); - Secpk1Fr { - array: a.bigint_sub(b).to_le_bytes() - } + Secpk1Fr { array: a.bigint_sub(b).to_le_bytes() } } } -impl Mul for Secpk1Fr { +impl Mul for Secpk1Fr { fn mul(self: Self, other: Secpk1Fr) -> Secpk1Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fr); - Secpk1Fr { - array: a.bigint_mul(b).to_le_bytes() - } + Secpk1Fr { array: a.bigint_mul(b).to_le_bytes() } } } -impl Div for Secpk1Fr { +impl Div for Secpk1Fr { fn div(self: Self, other: Secpk1Fr) -> Secpk1Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fr); - Secpk1Fr { - array: a.bigint_div(b).to_le_bytes() - } + Secpk1Fr { array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpk1Fr { @@ -194,19 +170,15 @@ struct Bn254Fr { impl BigField for Bn254Fr { fn from_le_bytes(bytes: [u8]) -> Bn254Fr { assert(bytes.len() <= 32); - let mut array = [0;32]; + let mut array = [0; 32]; for i in 0..bytes.len() { array[i] = bytes[i]; } - Bn254Fr { - array: array, - } + Bn254Fr { array } } - fn from_le_bytes_32(bytes: [u8;32]) -> Bn254Fr { - Bn254Fr { - array: bytes, - } + fn from_le_bytes_32(bytes: [u8; 32]) -> Bn254Fr { + Bn254Fr { array: bytes } } fn to_le_bytes(self) -> [u8] { @@ -214,40 +186,32 @@ impl BigField for Bn254Fr { } } -impl Add for Bn254Fr { +impl Add for Bn254Fr { fn add(self: Self, other: Bn254Fr) -> Bn254Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fr); - Bn254Fr { - array: a.bigint_add(b).to_le_bytes() - } + Bn254Fr { array: a.bigint_add(b).to_le_bytes() } } } -impl Sub for Bn254Fr { +impl Sub for Bn254Fr { fn sub(self: Self, other: Bn254Fr) -> Bn254Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fr); - Bn254Fr { - array: a.bigint_sub(b).to_le_bytes() - } + Bn254Fr { array: a.bigint_sub(b).to_le_bytes() } } } -impl Mul for Bn254Fr { +impl Mul for Bn254Fr { fn mul(self: Self, other: Bn254Fr) -> Bn254Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fr); - Bn254Fr { - array: a.bigint_mul(b).to_le_bytes() - } + Bn254Fr { array: a.bigint_mul(b).to_le_bytes() } } } -impl Div for Bn254Fr { +impl Div for Bn254Fr { fn div(self: Self, other: Bn254Fr) -> Bn254Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fr); - Bn254Fr { - array: a.bigint_div(b).to_le_bytes() - } + Bn254Fr { array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Bn254Fr { @@ -263,19 +227,15 @@ struct Bn254Fq { impl BigField for Bn254Fq { fn from_le_bytes(bytes: [u8]) -> Bn254Fq { assert(bytes.len() <= 32); - let mut array = [0;32]; + let mut array = [0; 32]; for i in 0..bytes.len() { array[i] = bytes[i]; } - Bn254Fq { - array: array, - } + Bn254Fq { array } } - fn from_le_bytes_32(bytes: [u8;32]) -> Bn254Fq { - Bn254Fq { - array: bytes, - } + fn from_le_bytes_32(bytes: [u8; 32]) -> Bn254Fq { + Bn254Fq { array: bytes } } fn to_le_bytes(self) -> [u8] { @@ -283,40 +243,32 @@ impl BigField for Bn254Fq { } } -impl Add for Bn254Fq { +impl Add for Bn254Fq { fn add(self: Self, other: Bn254Fq) -> Bn254Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fq); - Bn254Fq { - array: a.bigint_add(b).to_le_bytes() - } + Bn254Fq { array: a.bigint_add(b).to_le_bytes() } } } -impl Sub for Bn254Fq { +impl Sub for Bn254Fq { fn sub(self: Self, other: Bn254Fq) -> Bn254Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fq); - Bn254Fq { - array: a.bigint_sub(b).to_le_bytes() - } + Bn254Fq { array: a.bigint_sub(b).to_le_bytes() } } } -impl Mul for Bn254Fq { +impl Mul for Bn254Fq { fn mul(self: Self, other: Bn254Fq) -> Bn254Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fq); - Bn254Fq { - array: a.bigint_mul(b).to_le_bytes() - } + Bn254Fq { array: a.bigint_mul(b).to_le_bytes() } } } -impl Div for Bn254Fq { +impl Div for Bn254Fq { fn div(self: Self, other: Bn254Fq) -> Bn254Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fq); - Bn254Fq { - array: a.bigint_div(b).to_le_bytes() - } + Bn254Fq { array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Bn254Fq { @@ -332,19 +284,15 @@ struct Secpr1Fq { impl BigField for Secpr1Fq { fn from_le_bytes(bytes: [u8]) -> Secpr1Fq { assert(bytes.len() <= 32); - let mut array = [0;32]; + let mut array = [0; 32]; for i in 0..bytes.len() { array[i] = bytes[i]; } - Secpr1Fq { - array: array, - } + Secpr1Fq { array } } - fn from_le_bytes_32(bytes: [u8;32]) -> Secpr1Fq { - Secpr1Fq { - array: bytes, - } + fn from_le_bytes_32(bytes: [u8; 32]) -> Secpr1Fq { + Secpr1Fq { array: bytes } } fn to_le_bytes(self) -> [u8] { @@ -352,40 +300,32 @@ impl BigField for Secpr1Fq { } } -impl Add for Secpr1Fq { +impl Add for Secpr1Fq { fn add(self: Self, other: Secpr1Fq) -> Secpr1Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fq); - Secpr1Fq { - array: a.bigint_add(b).to_le_bytes() - } + Secpr1Fq { array: a.bigint_add(b).to_le_bytes() } } } -impl Sub for Secpr1Fq { +impl Sub for Secpr1Fq { fn sub(self: Self, other: Secpr1Fq) -> Secpr1Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fq); - Secpr1Fq { - array: a.bigint_sub(b).to_le_bytes() - } + Secpr1Fq { array: a.bigint_sub(b).to_le_bytes() } } } -impl Mul for Secpr1Fq { +impl Mul for Secpr1Fq { fn mul(self: Self, other: Secpr1Fq) -> Secpr1Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fq); - Secpr1Fq { - array: a.bigint_mul(b).to_le_bytes() - } + Secpr1Fq { array: a.bigint_mul(b).to_le_bytes() } } } -impl Div for Secpr1Fq { +impl Div for Secpr1Fq { fn div(self: Self, other: Secpr1Fq) -> Secpr1Fq { let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fq); let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fq); - Secpr1Fq { - array: a.bigint_div(b).to_le_bytes() - } + Secpr1Fq { array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpr1Fq { @@ -401,19 +341,15 @@ struct Secpr1Fr { impl BigField for Secpr1Fr { fn from_le_bytes(bytes: [u8]) -> Secpr1Fr { assert(bytes.len() <= 32); - let mut array = [0;32]; + let mut array = [0; 32]; for i in 0..bytes.len() { array[i] = bytes[i]; } - Secpr1Fr { - array: array, - } + Secpr1Fr { array } } - fn from_le_bytes_32(bytes: [u8;32]) -> Secpr1Fr { - Secpr1Fr { - array: bytes, - } + fn from_le_bytes_32(bytes: [u8; 32]) -> Secpr1Fr { + Secpr1Fr { array: bytes } } fn to_le_bytes(self) -> [u8] { @@ -421,40 +357,32 @@ impl BigField for Secpr1Fr { } } -impl Add for Secpr1Fr { +impl Add for Secpr1Fr { fn add(self: Self, other: Secpr1Fr) -> Secpr1Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fr); - Secpr1Fr { - array: a.bigint_add(b).to_le_bytes() - } + Secpr1Fr { array: a.bigint_add(b).to_le_bytes() } } } -impl Sub for Secpr1Fr { +impl Sub for Secpr1Fr { fn sub(self: Self, other: Secpr1Fr) -> Secpr1Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fr); - Secpr1Fr { - array: a.bigint_sub(b).to_le_bytes() - } + Secpr1Fr { array: a.bigint_sub(b).to_le_bytes() } } } -impl Mul for Secpr1Fr { +impl Mul for Secpr1Fr { fn mul(self: Self, other: Secpr1Fr) -> Secpr1Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fr); - Secpr1Fr { - array: a.bigint_mul(b).to_le_bytes() - } + Secpr1Fr { array: a.bigint_mul(b).to_le_bytes() } } } -impl Div for Secpr1Fr { +impl Div for Secpr1Fr { fn div(self: Self, other: Secpr1Fr) -> Secpr1Fr { let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fr); let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fr); - Secpr1Fr { - array: a.bigint_div(b).to_le_bytes() - } + Secpr1Fr { array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpr1Fr { diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr index 521604a4e20..e76116951c5 100644 --- a/noir_stdlib/src/cmp.nr +++ b/noir_stdlib/src/cmp.nr @@ -22,26 +22,74 @@ comptime fn derive_eq(s: StructDefinition) -> Quoted { } // docs:end:derive_eq -impl Eq for Field { fn eq(self, other: Field) -> bool { self == other } } +impl Eq for Field { + fn eq(self, other: Field) -> bool { + self == other + } +} -impl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } } -impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } -impl Eq for u16 { fn eq(self, other: u16) -> bool { self == other } } -impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } -impl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } } +impl Eq for u64 { + fn eq(self, other: u64) -> bool { + self == other + } +} +impl Eq for u32 { + fn eq(self, other: u32) -> bool { + self == other + } +} +impl Eq for u16 { + fn eq(self, other: u16) -> bool { + self == other + } +} +impl Eq for u8 { + fn eq(self, other: u8) -> bool { + self == other + } +} +impl Eq for u1 { + fn eq(self, other: u1) -> 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 } } +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 + } +} -impl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } } -impl Eq for bool { fn eq(self, other: bool) -> bool { self == other } } +impl Eq for () { + fn eq(_self: Self, _other: ()) -> bool { + true + } +} +impl Eq for bool { + fn eq(self, other: bool) -> bool { + self == other + } +} impl Eq for [T; N] where T: Eq { fn eq(self, other: [T; N]) -> bool { let mut result = true; - for i in 0 .. self.len() { + for i in 0..self.len() { result &= self[i].eq(other[i]); } result @@ -51,7 +99,7 @@ impl Eq for [T; N] where T: Eq { impl Eq for [T] where T: Eq { fn eq(self, other: [T]) -> bool { let mut result = self.len() == other.len(); - for i in 0 .. self.len() { + for i in 0..self.len() { result &= self[i].eq(other[i]); } result @@ -86,7 +134,11 @@ impl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq { impl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { fn eq(self, other: (A, B, C, D, E)) -> bool { - self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4) + self.0.eq(other.0) + & self.1.eq(other.1) + & self.2.eq(other.2) + & self.3.eq(other.3) + & self.4.eq(other.4) } } @@ -255,12 +307,10 @@ impl Ord for bool { } else { Ordering::greater() } + } else if other { + Ordering::less() } else { - if other { - Ordering::less() - } else { - Ordering::equal() - } + Ordering::equal() } } } @@ -270,7 +320,7 @@ impl Ord for [T; N] where T: Ord { // the ordering for the whole array. fn cmp(self, other: [T; N]) -> Ordering { let mut result = Ordering::equal(); - for i in 0 .. self.len() { + for i in 0..self.len() { if result == Ordering::equal() { let result_i = self[i].cmp(other[i]); @@ -290,7 +340,7 @@ impl Ord for [T] where T: Ord { // the ordering for the whole array. fn cmp(self, other: [T]) -> Ordering { let mut result = self.len().cmp(other.len()); - for i in 0 .. self.len() { + for i in 0..self.len() { if result == Ordering::equal() { let result_i = self[i].cmp(other[i]); diff --git a/noir_stdlib/src/collections/bounded_vec.nr b/noir_stdlib/src/collections/bounded_vec.nr index fede1b17c07..315e398f097 100644 --- a/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir_stdlib/src/collections/bounded_vec.nr @@ -428,13 +428,13 @@ impl Eq for BoundedVec where T: Eq { // // We make the assumption that the user has used the proper interface for working with `BoundedVec`s // rather than directly manipulating the internal fields as this can result in an inconsistent internal state. - + (self.len == other.len) & (self.storage == other.storage) } } impl From<[T; Len]> for BoundedVec { - fn from(array: [T; Len]) -> BoundedVec { + fn from(array: [T; Len]) -> BoundedVec { BoundedVec::from_array(array) } } diff --git a/noir_stdlib/src/collections/map.nr b/noir_stdlib/src/collections/map.nr index e84103aafc5..def15f718ca 100644 --- a/noir_stdlib/src/collections/map.nr +++ b/noir_stdlib/src/collections/map.nr @@ -50,12 +50,9 @@ struct Slot { _is_deleted: bool, } -impl Default for Slot{ - fn default() -> Self{ - Slot{ - _key_value: Option::none(), - _is_deleted: false - } +impl Default for Slot { + fn default() -> Self { + Slot { _key_value: Option::none(), _is_deleted: false } } } @@ -649,8 +646,7 @@ where K: Eq + Hash, V: Eq, B: BuildHasher, - H: Hasher -{ + H: Hasher { /// Checks if two HashMaps are equal. /// /// Example: @@ -668,22 +664,22 @@ where /// assert(map1 == map2); /// ``` fn eq(self, other: HashMap) -> bool { -// docs:end:eq + // docs:end:eq let mut equal = false; - if self.len() == other.len(){ + if self.len() == other.len() { equal = true; - for slot in self._table{ + for slot in self._table { // Not marked as deleted and has key-value. - if equal & slot.is_valid(){ + if equal & slot.is_valid() { let (key, value) = slot.key_value_unchecked(); let other_value = other.get(key); - if other_value.is_none(){ + if other_value.is_none() { equal = false; - }else{ + } else { let other_value = other_value.unwrap_unchecked(); - if value != other_value{ + if value != other_value { equal = false; } } @@ -699,8 +695,7 @@ where impl Default for HashMap where B: BuildHasher + Default, - H: Hasher + Default -{ + H: Hasher + Default { /// Constructs an empty HashMap. /// /// Example: diff --git a/noir_stdlib/src/collections/umap.nr b/noir_stdlib/src/collections/umap.nr index c71905e63b3..aa944404751 100644 --- a/noir_stdlib/src/collections/umap.nr +++ b/noir_stdlib/src/collections/umap.nr @@ -31,12 +31,9 @@ struct Slot { _is_deleted: bool, } -impl Default for Slot{ - fn default() -> Self{ - Slot{ - _key_value: Option::none(), - _is_deleted: false - } +impl Default for Slot { + fn default() -> Self { + Slot { _key_value: Option::none(), _is_deleted: false } } } @@ -425,25 +422,26 @@ where K: Eq + Hash, V: Eq, B: BuildHasher, - H: Hasher -{ + H: Hasher { fn eq(self, other: UHashMap) -> bool { -// docs:end:eq + // docs:end:eq let mut equal = false; - if self.len() == other.len(){ + if self.len() == other.len() { equal = true; - for slot in self._table{ + for slot in self._table { // Not marked as deleted and has key-value. - if equal & slot.is_valid(){ + if equal & slot.is_valid() { let (key, value) = slot.key_value_unchecked(); - let other_value = unsafe { other.get(key) }; + let other_value = unsafe { + other.get(key) + }; - if other_value.is_none(){ + if other_value.is_none() { equal = false; - }else{ + } else { let other_value = other_value.unwrap_unchecked(); - if value != other_value{ + if value != other_value { equal = false; } } @@ -459,10 +457,9 @@ where impl Default for UHashMap where B: BuildHasher + Default, - H: Hasher + Default -{ + H: Hasher + Default { fn default() -> Self { -// docs:end:default + // docs:end:default UHashMap::with_hasher(B::default()) } } diff --git a/noir_stdlib/src/convert.nr b/noir_stdlib/src/convert.nr index d3537df3c5e..0b2bd4f2eb7 100644 --- a/noir_stdlib/src/convert.nr +++ b/noir_stdlib/src/convert.nr @@ -5,9 +5,9 @@ trait From { // docs:end:from-trait impl From for T { - fn from(input: T) -> T { - input - } + fn from(input: T) -> T { + input + } } // docs:start:into-trait @@ -16,37 +16,101 @@ trait Into { } impl Into for U where T: From { - fn into(self) -> T { - T::from(self) - } + fn into(self) -> T { + T::from(self) + } } // docs:end:into-trait // docs:start:from-impls // Unsigned integers -impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } +impl From for u32 { + fn from(value: u8) -> u32 { + value as u32 + } +} -impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } -impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } +impl From for u64 { + fn from(value: u8) -> 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: u32) -> Field { value as Field } } -impl From for Field { fn from(value: u64) -> Field { value as Field } } +impl From for Field { + fn from(value: u8) -> 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 i32 { fn from(value: i8) -> i32 { value as i32 } } +impl From for i32 { + fn from(value: i8) -> i32 { + value as i32 + } +} -impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } -impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } +impl From for i64 { + fn from(value: i8) -> 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 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 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 } } +impl From for u8 { + fn from(value: bool) -> u8 { + value as u8 + } +} +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 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 + } +} // docs:end:from-impls diff --git a/noir_stdlib/src/default.nr b/noir_stdlib/src/default.nr index 3ac5fbb394e..3dcc04c7d0c 100644 --- a/noir_stdlib/src/default.nr +++ b/noir_stdlib/src/default.nr @@ -15,21 +15,69 @@ comptime fn derive_default(s: StructDefinition) -> Quoted { crate::meta::make_trait_impl(s, name, signature, for_each_field, quote { , }, body) } -impl Default for Field { fn default() -> Field { 0 } } +impl Default for Field { + fn default() -> Field { + 0 + } +} -impl Default for u1 { fn default() -> u1 { 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 u1 { + fn default() -> u1 { + 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 } } +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 + } +} -impl Default for () { fn default() -> () { () } } -impl Default for bool { fn default() -> bool { false } } +impl Default for () { + fn default() -> () { + () + } +} +impl Default for bool { + fn default() -> bool { + false + } +} impl Default for [T; N] where T: Default { fn default() -> [T; N] { diff --git a/noir_stdlib/src/ec/montcurve.nr b/noir_stdlib/src/ec/montcurve.nr index 12b48d66b9d..676b1cd81a7 100644 --- a/noir_stdlib/src/ec/montcurve.nr +++ b/noir_stdlib/src/ec/montcurve.nr @@ -276,7 +276,8 @@ mod curvegroup { impl Eq for Point { fn eq(self, p: Self) -> bool { - (self.z == p.z) | (((self.x * self.z) == (p.x * p.z)) & ((self.y * self.z) == (p.y * p.z))) + (self.z == p.z) + | (((self.x * self.z) == (p.x * p.z)) & ((self.y * self.z) == (p.y * p.z))) } } diff --git a/noir_stdlib/src/ec/swcurve.nr b/noir_stdlib/src/ec/swcurve.nr index 4139492af63..9620b23948d 100644 --- a/noir_stdlib/src/ec/swcurve.nr +++ b/noir_stdlib/src/ec/swcurve.nr @@ -60,11 +60,10 @@ mod affine { impl Eq for Point { fn eq(self, p: Self) -> bool { - let Self {x: x1, y: y1, infty: inf1} = self; + let Self {x: x1, y: y1, infty: inf1} = self; let Self {x: x2, y: y2, infty: inf2} = p; - (inf1 & inf2) - | (!inf1 & !inf2 & (x1 == x2) & (y1 == y2)) + (inf1 & inf2) | (!inf1 & !inf2 & (x1 == x2) & (y1 == y2)) } } @@ -245,10 +244,13 @@ mod curvegroup { impl Eq for Point { fn eq(self, p: Self) -> bool { - let Self {x: x1, y: y1, z: z1} = self; + let Self {x: x1, y: y1, z: z1} = self; let Self {x: x2, y: y2, z: z2} = p; - ((z1 == 0) & (z2 == 0)) | ((z1 != 0) & (z2 != 0) & (x1*z2*z2 == x2*z1*z1) & (y1*z2*z2*z2 == y2*z1*z1*z1)) + ((z1 == 0) & (z2 == 0)) | ((z1 != 0) + & (z2 != 0) + & (x1 * z2 * z2 == x2 * z1 * z1) + & (y1 * z2 * z2 * z2 == y2 * z1 * z1 * z1)) } } diff --git a/noir_stdlib/src/ec/tecurve.nr b/noir_stdlib/src/ec/tecurve.nr index 2ba3fd4401c..9973678a048 100644 --- a/noir_stdlib/src/ec/tecurve.nr +++ b/noir_stdlib/src/ec/tecurve.nr @@ -70,7 +70,7 @@ mod affine { impl Eq for Point { fn eq(self, p: Self) -> bool { - let Self {x: x1, y: y1} = self; + let Self {x: x1, y: y1} = self; let Self {x: x2, y: y2} = p; (x1 == x2) & (y1 == y2) @@ -261,7 +261,7 @@ mod curvegroup { let Self {x: x1, y: y1, t: _t1, z: z1} = self; let Self {x: x2, y: y2, t: _t2, z:z2} = p; - (x1*z2 == x2*z1) & (y1*z2 == y2*z1) + (x1 * z2 == x2 * z1) & (y1 * z2 == y2 * z1) } } diff --git a/noir_stdlib/src/embedded_curve_ops.nr b/noir_stdlib/src/embedded_curve_ops.nr index 6b70b6ddef0..094ad5204c3 100644 --- a/noir_stdlib/src/embedded_curve_ops.nr +++ b/noir_stdlib/src/embedded_curve_ops.nr @@ -25,14 +25,14 @@ impl EmbeddedCurvePoint { impl Add for EmbeddedCurvePoint { /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity - fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { embedded_curve_add(self, other) } } impl Sub for EmbeddedCurvePoint { /// Points subtraction operation, using addition and negation - fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { self + other.neg() } } @@ -40,19 +40,16 @@ impl Sub for EmbeddedCurvePoint { impl Neg for EmbeddedCurvePoint { /// Negates a point P, i.e returns -P, by negating the y coordinate. /// If the point is at infinity, then the result is also at infinity. - fn neg(self) -> EmbeddedCurvePoint { - EmbeddedCurvePoint { - x: self.x, - y: -self.y, - is_infinite: self.is_infinite - } + fn neg(self) -> EmbeddedCurvePoint { + EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite } } } impl Eq for EmbeddedCurvePoint { /// Checks whether two points are equal fn eq(self: Self, b: EmbeddedCurvePoint) -> bool { - (self.is_infinite & b.is_infinite) | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y)) + (self.is_infinite & b.is_infinite) + | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y)) } } diff --git a/noir_stdlib/src/hash/mimc.nr b/noir_stdlib/src/hash/mimc.nr index a16a73c5bc5..6145a387f26 100644 --- a/noir_stdlib/src/hash/mimc.nr +++ b/noir_stdlib/src/hash/mimc.nr @@ -142,15 +142,13 @@ impl Hasher for MimcHasher { r } - fn write(&mut self, input: Field){ + fn write(&mut self, input: Field) { self._state = self._state.push_back(input); } } -impl Default for MimcHasher{ - fn default() -> Self{ - MimcHasher { - _state: &[], - } +impl Default for MimcHasher { + fn default() -> Self { + MimcHasher { _state: &[] } } } diff --git a/noir_stdlib/src/hash/mod.nr b/noir_stdlib/src/hash/mod.nr index 0e15595ff40..4c67a0cfa8b 100644 --- a/noir_stdlib/src/hash/mod.nr +++ b/noir_stdlib/src/hash/mod.nr @@ -170,84 +170,82 @@ struct BuildHasherDefault; impl BuildHasher for BuildHasherDefault where - H: Hasher + Default -{ - fn build_hasher(_self: Self) -> H{ + H: Hasher + Default { + fn build_hasher(_self: Self) -> H { H::default() } } impl Default for BuildHasherDefault where - H: Hasher + Default -{ - fn default() -> Self{ - BuildHasherDefault{} - } + H: Hasher + Default { + fn default() -> Self { + BuildHasherDefault {} + } } impl Hash for Field { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self); } } impl Hash for u1 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for u8 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for u16 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for u32 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for u64 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for i8 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for i16 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for i32 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for i64 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } impl Hash for bool { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self as Field); } } @@ -257,14 +255,14 @@ impl Hash for () { } impl Hash for U128 { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { H::write(state, self.lo as Field); H::write(state, self.hi as Field); } } impl Hash for [T; N] where T: Hash { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { for elem in self { elem.hash(state); } @@ -272,7 +270,7 @@ impl Hash for [T; N] where T: Hash { } impl Hash for [T] where T: Hash { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { self.len().hash(state); for elem in self { elem.hash(state); @@ -281,14 +279,14 @@ impl Hash for [T] where T: Hash { } impl Hash for (A, B) where A: Hash, B: Hash { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { self.0.hash(state); self.1.hash(state); } } impl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { self.0.hash(state); self.1.hash(state); self.2.hash(state); @@ -296,7 +294,7 @@ impl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash { } impl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { self.0.hash(state); self.1.hash(state); self.2.hash(state); @@ -305,7 +303,7 @@ impl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash } impl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash { - fn hash(self, state: &mut H) where H: Hasher{ + fn hash(self, state: &mut H) where H: Hasher { self.0.hash(state); self.1.hash(state); self.2.hash(state); diff --git a/noir_stdlib/src/hash/poseidon/mod.nr b/noir_stdlib/src/hash/poseidon/mod.nr index cf9b6187c02..47403e0c1d3 100644 --- a/noir_stdlib/src/hash/poseidon/mod.nr +++ b/noir_stdlib/src/hash/poseidon/mod.nr @@ -177,16 +177,16 @@ impl Hasher for PoseidonHasher { assert(len < 16); if len == 1 { result = bn254::hash_1([self._state[0]]); - } + } if len == 2 { result = bn254::hash_2([self._state[0],self._state[1]]); - } + } if len == 3 { result = bn254::hash_3([self._state[0],self._state[1],self._state[2]]); - } + } if len == 4 { result = bn254::hash_4([self._state[0],self._state[1],self._state[2],self._state[3]]); - } + } if len == 5 { result = bn254::hash_5([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4]]); } @@ -220,20 +220,18 @@ impl Hasher for PoseidonHasher { if len == 15 { result = bn254::hash_15([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12], self._state[13], self._state[14]]); } - + result } - fn write(&mut self, input: Field){ + fn write(&mut self, input: Field) { self._state = self._state.push_back(input); } } -impl Default for PoseidonHasher{ - fn default() -> Self{ - PoseidonHasher{ - _state: &[], - } +impl Default for PoseidonHasher { + fn default() -> Self { + PoseidonHasher { _state: &[] } } } diff --git a/noir_stdlib/src/hash/poseidon2.nr b/noir_stdlib/src/hash/poseidon2.nr index 902d3cc8104..9f28cf3e904 100644 --- a/noir_stdlib/src/hash/poseidon2.nr +++ b/noir_stdlib/src/hash/poseidon2.nr @@ -88,7 +88,7 @@ struct Poseidon2Hasher{ impl Hasher for Poseidon2Hasher { fn finish(self) -> Field { - let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64) + let iv : Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64) let mut sponge = Poseidon2::new(iv); for i in 0..self._state.len() { sponge.absorb(self._state[i]); @@ -96,15 +96,13 @@ impl Hasher for Poseidon2Hasher { sponge.squeeze() } - fn write(&mut self, input: Field){ + fn write(&mut self, input: Field) { self._state = self._state.push_back(input); } } impl Default for Poseidon2Hasher { fn default() -> Self { - Poseidon2Hasher { - _state: &[], - } + Poseidon2Hasher { _state: &[] } } } diff --git a/noir_stdlib/src/meta/function_def.nr b/noir_stdlib/src/meta/function_def.nr index 5d536d60ae1..cd5f9cc79fb 100644 --- a/noir_stdlib/src/meta/function_def.nr +++ b/noir_stdlib/src/meta/function_def.nr @@ -11,7 +11,7 @@ impl FunctionDefinition { #[builtin(function_def_has_named_attribute)] // docs:start:has_named_attribute - comptime fn has_named_attribute(self, name: Quoted) -> bool {} + comptime fn has_named_attribute(self, name: str) -> bool {} // docs:end:has_named_attribute #[builtin(function_def_is_unconstrained)] @@ -64,3 +64,21 @@ impl FunctionDefinition { comptime fn set_unconstrained(self, value: bool) {} // docs:end:set_unconstrained } + +impl crate::hash::Hash for FunctionDefinition { + comptime fn hash(self, state: &mut H) where H: crate::hash::Hasher { + state.write(function_def_hash(self)) + } +} + +impl crate::cmp::Eq for FunctionDefinition { + comptime fn eq(self, other: Self) -> bool { + function_def_eq(self, other) + } +} + +#[builtin(function_def_eq)] +comptime fn function_def_eq(_first: FunctionDefinition, _second: FunctionDefinition) -> bool {} + +#[builtin(function_def_hash)] +comptime fn function_def_hash(_function: FunctionDefinition) -> Field {} diff --git a/noir_stdlib/src/meta/module.nr b/noir_stdlib/src/meta/module.nr index 6f936bf4c57..1b29301c4ef 100644 --- a/noir_stdlib/src/meta/module.nr +++ b/noir_stdlib/src/meta/module.nr @@ -6,21 +6,44 @@ impl Module { #[builtin(module_has_named_attribute)] // docs:start:has_named_attribute - comptime fn has_named_attribute(self, name: Quoted) -> bool {} + comptime fn has_named_attribute(self, name: str) -> bool {} // docs:end:has_named_attribute #[builtin(module_is_contract)] -// docs:start:is_contract + // docs:start:is_contract comptime fn is_contract(self) -> bool {} // docs:end:is_contract #[builtin(module_functions)] -// docs:start:functions + // docs:start:functions comptime fn functions(self) -> [FunctionDefinition] {} // docs:end:functions + #[builtin(module_structs)] + // docs:start:structs + comptime fn structs(self) -> [StructDefinition] {} + // docs:end:structs + #[builtin(module_name)] -// docs:start:name + // docs:start:name comptime fn name(self) -> Quoted {} // docs:end:name } + +impl crate::hash::Hash for Module { + comptime fn hash(self, state: &mut H) where H: crate::hash::Hasher { + state.write(module_hash(self)) + } +} + +impl crate::cmp::Eq for Module { + comptime fn eq(self, other: Self) -> bool { + module_eq(self, other) + } +} + +#[builtin(module_eq)] +comptime fn module_eq(_first: Module, _second: Module) -> bool {} + +#[builtin(module_hash)] +comptime fn module_hash(_module: Module) -> Field {} diff --git a/noir_stdlib/src/meta/op.nr b/noir_stdlib/src/meta/op.nr index 4b104486201..31a815f07ba 100644 --- a/noir_stdlib/src/meta/op.nr +++ b/noir_stdlib/src/meta/op.nr @@ -1,3 +1,4 @@ +#[derive(Eq, Hash)] struct UnaryOp { op: Field } @@ -45,6 +46,7 @@ impl UnaryOp { } } +#[derive(Eq, Hash)] struct BinaryOp { op: Field } diff --git a/noir_stdlib/src/meta/quoted.nr b/noir_stdlib/src/meta/quoted.nr index ff74580ce20..6e8d001c57c 100644 --- a/noir_stdlib/src/meta/quoted.nr +++ b/noir_stdlib/src/meta/quoted.nr @@ -34,6 +34,14 @@ impl Eq for Quoted { } } +impl crate::hash::Hash for Quoted { + comptime fn hash(self, state: &mut H) where H: crate::hash::Hasher { + state.write(quoted_hash(self)) + } +} + #[builtin(quoted_eq)] comptime fn quoted_eq(_first: Quoted, _second: Quoted) -> bool {} +#[builtin(quoted_hash)] +comptime fn quoted_hash(_quoted: Quoted) -> Field {} diff --git a/noir_stdlib/src/meta/struct_def.nr b/noir_stdlib/src/meta/struct_def.nr index e3621b3482e..b17c0d37613 100644 --- a/noir_stdlib/src/meta/struct_def.nr +++ b/noir_stdlib/src/meta/struct_def.nr @@ -18,7 +18,7 @@ impl StructDefinition { #[builtin(struct_def_has_named_attribute)] // docs:start:has_named_attribute - comptime fn has_named_attribute(self, name: Quoted) -> bool {} + comptime fn has_named_attribute(self, name: str) -> bool {} // docs:end:has_named_attribute /// Return each generic on this struct. @@ -53,3 +53,21 @@ impl StructDefinition { comptime fn set_fields(self, new_fields: [(Quoted, Type)]) {} // docs:end:set_fields } + +impl crate::hash::Hash for StructDefinition { + comptime fn hash(self, state: &mut H) where H: crate::hash::Hasher { + state.write(struct_def_hash(self)) + } +} + +impl crate::cmp::Eq for StructDefinition { + comptime fn eq(self, other: Self) -> bool { + struct_def_eq(self, other) + } +} + +#[builtin(struct_def_eq)] +comptime fn struct_def_eq(_first: StructDefinition, _second: StructDefinition) -> bool {} + +#[builtin(struct_def_hash)] +comptime fn struct_def_hash(_struct: StructDefinition) -> Field {} diff --git a/noir_stdlib/src/meta/typ.nr b/noir_stdlib/src/meta/typ.nr index d692f6e5a7e..5a748c2c823 100644 --- a/noir_stdlib/src/meta/typ.nr +++ b/noir_stdlib/src/meta/typ.nr @@ -69,5 +69,14 @@ impl Eq for Type { } } +impl crate::hash::Hash for Type { + comptime fn hash(self, state: &mut H) where H: crate::hash::Hasher { + state.write(type_hash(self)) + } +} + #[builtin(type_eq)] comptime fn type_eq(_first: Type, _second: Type) -> bool {} + +#[builtin(type_hash)] +comptime fn type_hash(_typ: Type) -> Field {} diff --git a/noir_stdlib/src/ops/arith.nr b/noir_stdlib/src/ops/arith.nr index 918c8e9bc28..653dfd59978 100644 --- a/noir_stdlib/src/ops/arith.nr +++ b/noir_stdlib/src/ops/arith.nr @@ -4,18 +4,58 @@ trait Add { } // docs:end:add-trait -impl Add for Field { fn add(self, other: Field) -> Field { self + other } } +impl Add for Field { + fn add(self, other: Field) -> Field { + self + other + } +} -impl Add for u64 { fn add(self, other: u64) -> u64 { self + other } } -impl Add for u32 { fn add(self, other: u32) -> u32 { self + other } } -impl Add for u16 { fn add(self, other: u16) -> u16 { self + other } } -impl Add for u8 { fn add(self, other: u8) -> u8 { self + other } } -impl Add for u1 { fn add(self, other: u1) -> u1 { self + other } } +impl Add for u64 { + fn add(self, other: u64) -> u64 { + self + other + } +} +impl Add for u32 { + fn add(self, other: u32) -> u32 { + self + other + } +} +impl Add for u16 { + fn add(self, other: u16) -> u16 { + self + other + } +} +impl Add for u8 { + fn add(self, other: u8) -> u8 { + self + other + } +} +impl Add for u1 { + fn add(self, other: u1) -> u1 { + 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 } } +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 + } +} // docs:start:sub-trait trait Sub { @@ -23,18 +63,58 @@ trait Sub { } // docs:end:sub-trait -impl Sub for Field { fn sub(self, other: Field) -> Field { self - other } } +impl Sub for Field { + fn sub(self, other: Field) -> Field { + self - other + } +} -impl Sub for u64 { fn sub(self, other: u64) -> u64 { self - other } } -impl Sub for u32 { fn sub(self, other: u32) -> u32 { self - other } } -impl Sub for u16 { fn sub(self, other: u16) -> u16 { self - other } } -impl Sub for u8 { fn sub(self, other: u8) -> u8 { self - other } } -impl Sub for u1 { fn sub(self, other: u1) -> u1 { self - other } } +impl Sub for u64 { + fn sub(self, other: u64) -> u64 { + self - other + } +} +impl Sub for u32 { + fn sub(self, other: u32) -> u32 { + self - other + } +} +impl Sub for u16 { + fn sub(self, other: u16) -> u16 { + self - other + } +} +impl Sub for u8 { + fn sub(self, other: u8) -> u8 { + self - other + } +} +impl Sub for u1 { + fn sub(self, other: u1) -> u1 { + 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 } } +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 + } +} // docs:start:mul-trait trait Mul { @@ -42,18 +122,58 @@ trait Mul { } // docs:end:mul-trait -impl Mul for Field { fn mul(self, other: Field) -> Field { self * other } } +impl Mul for Field { + fn mul(self, other: Field) -> Field { + self * other + } +} -impl Mul for u64 { fn mul(self, other: u64) -> u64 { self * other } } -impl Mul for u32 { fn mul(self, other: u32) -> u32 { self * other } } -impl Mul for u16 { fn mul(self, other: u16) -> u16 { self * other } } -impl Mul for u8 { fn mul(self, other: u8) -> u8 { self * other } } -impl Mul for u1 { fn mul(self, other: u1) -> u1 { self * other } } +impl Mul for u64 { + fn mul(self, other: u64) -> u64 { + self * other + } +} +impl Mul for u32 { + fn mul(self, other: u32) -> u32 { + self * other + } +} +impl Mul for u16 { + fn mul(self, other: u16) -> u16 { + self * other + } +} +impl Mul for u8 { + fn mul(self, other: u8) -> u8 { + self * other + } +} +impl Mul for u1 { + fn mul(self, other: u1) -> u1 { + 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 } } +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 + } +} // docs:start:div-trait trait Div { @@ -61,18 +181,58 @@ trait Div { } // docs:end:div-trait -impl Div for Field { fn div(self, other: Field) -> Field { self / other } } +impl Div for Field { + fn div(self, other: Field) -> Field { + self / other + } +} -impl Div for u64 { fn div(self, other: u64) -> u64 { self / other } } -impl Div for u32 { fn div(self, other: u32) -> u32 { self / other } } -impl Div for u16 { fn div(self, other: u16) -> u16 { self / other } } -impl Div for u8 { fn div(self, other: u8) -> u8 { self / other } } -impl Div for u1 { fn div(self, other: u1) -> u1 { self / other } } +impl Div for u64 { + fn div(self, other: u64) -> u64 { + self / other + } +} +impl Div for u32 { + fn div(self, other: u32) -> u32 { + self / other + } +} +impl Div for u16 { + fn div(self, other: u16) -> u16 { + self / other + } +} +impl Div for u8 { + fn div(self, other: u8) -> u8 { + self / other + } +} +impl Div for u1 { + fn div(self, other: u1) -> u1 { + 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 } } +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 + } +} // docs:start:rem-trait trait Rem{ @@ -80,16 +240,52 @@ trait Rem{ } // docs:end:rem-trait -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u1 { fn rem(self, other: u1) -> u1 { self % other } } +impl Rem for u64 { + fn rem(self, other: u64) -> u64 { + self % other + } +} +impl Rem for u32 { + fn rem(self, other: u32) -> u32 { + self % other + } +} +impl Rem for u16 { + fn rem(self, other: u16) -> u16 { + self % other + } +} +impl Rem for u8 { + fn rem(self, other: u8) -> u8 { + self % other + } +} +impl Rem for u1 { + fn rem(self, other: u1) -> u1 { + 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 } } +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 + } +} // docs:start:neg-trait trait Neg { @@ -98,11 +294,31 @@ trait Neg { // docs:end:neg-trait // docs:start:neg-trait-impls -impl Neg for Field { fn neg(self) -> Field { -self } } +impl Neg for Field { + fn neg(self) -> Field { + -self + } +} -impl Neg for i8 { fn neg(self) -> i8 { -self } } -impl Neg for i16 { fn neg(self) -> i16 { -self } } -impl Neg for i32 { fn neg(self) -> i32 { -self } } -impl Neg for i64 { fn neg(self) -> i64 { -self } } +impl Neg for i8 { + fn neg(self) -> i8 { + -self + } +} +impl Neg for i16 { + fn neg(self) -> i16 { + -self + } +} +impl Neg for i32 { + fn neg(self) -> i32 { + -self + } +} +impl Neg for i64 { + fn neg(self) -> i64 { + -self + } +} // docs:end:neg-trait-impls diff --git a/noir_stdlib/src/ops/bit.nr b/noir_stdlib/src/ops/bit.nr index 015d0008e7a..0c0329efe4c 100644 --- a/noir_stdlib/src/ops/bit.nr +++ b/noir_stdlib/src/ops/bit.nr @@ -5,18 +5,58 @@ trait Not { // docs:end:not-trait // docs:start:not-trait-impls -impl Not for bool { fn not(self) -> bool { !self } } - -impl Not for u64 { fn not(self) -> u64 { !self } } -impl Not for u32 { fn not(self) -> u32 { !self } } -impl Not for u16 { fn not(self) -> u16 { !self } } -impl Not for u8 { fn not(self) -> u8 { !self } } -impl Not for u1 { fn not(self) -> u1 { !self } } - -impl Not for i8 { fn not(self) -> i8 { !self } } -impl Not for i16 { fn not(self) -> i16 { !self } } -impl Not for i32 { fn not(self) -> i32 { !self } } -impl Not for i64 { fn not(self) -> i64 { !self } } +impl Not for bool { + fn not(self) -> bool { + !self + } +} + +impl Not for u64 { + fn not(self) -> u64 { + !self + } +} +impl Not for u32 { + fn not(self) -> u32 { + !self + } +} +impl Not for u16 { + fn not(self) -> u16 { + !self + } +} +impl Not for u8 { + fn not(self) -> u8 { + !self + } +} +impl Not for u1 { + fn not(self) -> u1 { + !self + } +} + +impl Not for i8 { + fn not(self) -> i8 { + !self + } +} +impl Not for i16 { + fn not(self) -> i16 { + !self + } +} +impl Not for i32 { + fn not(self) -> i32 { + !self + } +} +impl Not for i64 { + fn not(self) -> i64 { + !self + } +} // docs:end:not-trait-impls // docs:start:bitor-trait @@ -25,18 +65,58 @@ trait BitOr { } // docs:end:bitor-trait -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } +impl BitOr for bool { + fn bitor(self, other: bool) -> bool { + self | other + } +} -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u1 { fn bitor(self, other: u1) -> u1 { self | other } } +impl BitOr for u64 { + fn bitor(self, other: u64) -> u64 { + self | other + } +} +impl BitOr for u32 { + fn bitor(self, other: u32) -> u32 { + self | other + } +} +impl BitOr for u16 { + fn bitor(self, other: u16) -> u16 { + self | other + } +} +impl BitOr for u8 { + fn bitor(self, other: u8) -> u8 { + self | other + } +} +impl BitOr for u1 { + fn bitor(self, other: u1) -> u1 { + 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 } } +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 + } +} // docs:start:bitand-trait trait BitAnd { @@ -44,18 +124,58 @@ trait BitAnd { } // docs:end:bitand-trait -impl BitAnd for bool { fn bitand(self, other: bool) -> bool { self & other } } +impl BitAnd for bool { + fn bitand(self, other: bool) -> bool { + self & other + } +} -impl BitAnd for u64 { fn bitand(self, other: u64) -> u64 { self & other } } -impl BitAnd for u32 { fn bitand(self, other: u32) -> u32 { self & other } } -impl BitAnd for u16 { fn bitand(self, other: u16) -> u16 { self & other } } -impl BitAnd for u8 { fn bitand(self, other: u8) -> u8 { self & other } } -impl BitAnd for u1 { fn bitand(self, other: u1) -> u1 { self & other } } +impl BitAnd for u64 { + fn bitand(self, other: u64) -> u64 { + self & other + } +} +impl BitAnd for u32 { + fn bitand(self, other: u32) -> u32 { + self & other + } +} +impl BitAnd for u16 { + fn bitand(self, other: u16) -> u16 { + self & other + } +} +impl BitAnd for u8 { + fn bitand(self, other: u8) -> u8 { + self & other + } +} +impl BitAnd for u1 { + fn bitand(self, other: u1) -> u1 { + 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 } } +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 + } +} // docs:start:bitxor-trait trait BitXor { @@ -63,18 +183,58 @@ trait BitXor { } // docs:end:bitxor-trait -impl BitXor for bool { fn bitxor(self, other: bool) -> bool { self ^ other } } +impl BitXor for bool { + fn bitxor(self, other: bool) -> bool { + self ^ other + } +} -impl BitXor for u64 { fn bitxor(self, other: u64) -> u64 { self ^ other } } -impl BitXor for u32 { fn bitxor(self, other: u32) -> u32 { self ^ other } } -impl BitXor for u16 { fn bitxor(self, other: u16) -> u16 { self ^ other } } -impl BitXor for u8 { fn bitxor(self, other: u8) -> u8 { self ^ other } } -impl BitXor for u1 { fn bitxor(self, other: u1) -> u1 { self ^ other } } +impl BitXor for u64 { + fn bitxor(self, other: u64) -> u64 { + self ^ other + } +} +impl BitXor for u32 { + fn bitxor(self, other: u32) -> u32 { + self ^ other + } +} +impl BitXor for u16 { + fn bitxor(self, other: u16) -> u16 { + self ^ other + } +} +impl BitXor for u8 { + fn bitxor(self, other: u8) -> u8 { + self ^ other + } +} +impl BitXor for u1 { + fn bitxor(self, other: u1) -> u1 { + 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 } } +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 + } +} // docs:start:shl-trait trait Shl { @@ -82,16 +242,52 @@ trait Shl { } // docs:end:shl-trait -impl Shl for u32 { fn shl(self, other: u8) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u8) -> u64 { self << other } } -impl Shl for u16 { fn shl(self, other: u8) -> u16 { self << other } } -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u1 { fn shl(self, other: u8) -> u1 { self << other } } +impl Shl for u32 { + fn shl(self, other: u8) -> u32 { + self << other + } +} +impl Shl for u64 { + fn shl(self, other: u8) -> u64 { + self << other + } +} +impl Shl for u16 { + fn shl(self, other: u8) -> u16 { + self << other + } +} +impl Shl for u8 { + fn shl(self, other: u8) -> u8 { + self << other + } +} +impl Shl for u1 { + fn shl(self, other: u8) -> u1 { + self << other + } +} -impl Shl for i8 { fn shl(self, other: u8) -> i8 { self << other } } -impl Shl for i16 { fn shl(self, other: u8) -> i16 { self << other } } -impl Shl for i32 { fn shl(self, other: u8) -> i32 { self << other } } -impl Shl for i64 { fn shl(self, other: u8) -> i64 { self << other } } +impl Shl for i8 { + fn shl(self, other: u8) -> i8 { + self << other + } +} +impl Shl for i16 { + fn shl(self, other: u8) -> i16 { + self << other + } +} +impl Shl for i32 { + fn shl(self, other: u8) -> i32 { + self << other + } +} +impl Shl for i64 { + fn shl(self, other: u8) -> i64 { + self << other + } +} // docs:start:shr-trait trait Shr { @@ -99,14 +295,50 @@ trait Shr { } // docs:end:shr-trait -impl Shr for u64 { fn shr(self, other: u8) -> u64 { self >> other } } -impl Shr for u32 { fn shr(self, other: u8) -> u32 { self >> other } } -impl Shr for u16 { fn shr(self, other: u8) -> u16 { self >> other } } -impl Shr for u8 { fn shr(self, other: u8) -> u8 { self >> other } } -impl Shr for u1 { fn shr(self, other: u8) -> u1 { self >> other } } +impl Shr for u64 { + fn shr(self, other: u8) -> u64 { + self >> other + } +} +impl Shr for u32 { + fn shr(self, other: u8) -> u32 { + self >> other + } +} +impl Shr for u16 { + fn shr(self, other: u8) -> u16 { + self >> other + } +} +impl Shr for u8 { + fn shr(self, other: u8) -> u8 { + self >> other + } +} +impl Shr for u1 { + fn shr(self, other: u8) -> u1 { + self >> other + } +} -impl Shr for i8 { fn shr(self, other: u8) -> i8 { self >> other } } -impl Shr for i16 { fn shr(self, other: u8) -> i16 { self >> other } } -impl Shr for i32 { fn shr(self, other: u8) -> i32 { self >> other } } -impl Shr for i64 { fn shr(self, other: u8) -> i64 { self >> other } } +impl Shr for i8 { + fn shr(self, other: u8) -> i8 { + self >> other + } +} +impl Shr for i16 { + fn shr(self, other: u8) -> i16 { + self >> other + } +} +impl Shr for i32 { + fn shr(self, other: u8) -> i32 { + self >> other + } +} +impl Shr for i64 { + fn shr(self, other: u8) -> i64 { + self >> other + } +} diff --git a/noir_stdlib/src/option.nr b/noir_stdlib/src/option.nr index 5b6b36679f8..2823ba8af1b 100644 --- a/noir_stdlib/src/option.nr +++ b/noir_stdlib/src/option.nr @@ -195,12 +195,10 @@ impl Ord for Option where T: Ord { } else { Ordering::greater() } + } else if other._is_some { + Ordering::less() } else { - if other._is_some { - Ordering::less() - } else { - Ordering::equal() - } + Ordering::equal() } } } diff --git a/noir_stdlib/src/uint128.nr b/noir_stdlib/src/uint128.nr index ac7f744cb3b..91c3369f889 100644 --- a/noir_stdlib/src/uint128.nr +++ b/noir_stdlib/src/uint128.nr @@ -165,14 +165,11 @@ impl Add for U128 { fn add(self: Self, b: U128) -> U128 { let low = self.lo + b.lo; let lo = low as u64 as Field; - let carry = (low - lo) / pow64; + let carry = (low - lo) / pow64; let high = self.hi + b.hi + carry; let hi = high as u64 as Field; assert(hi == high, "attempt to add with overflow"); - U128 { - lo, - hi, - } + U128 { lo, hi } } } @@ -184,30 +181,24 @@ impl Sub for U128 { let high = self.hi - b.hi - borrow; let hi = high as u64 as Field; assert(hi == high, "attempt to subtract with underflow"); - U128 { - lo, - hi, - } + U128 { lo, hi } } } impl Mul for U128 { fn mul(self: Self, b: U128) -> U128 { - assert(self.hi*b.hi == 0, "attempt to multiply with overflow"); - let low = self.lo*b.lo; + assert(self.hi * b.hi == 0, "attempt to multiply with overflow"); + let low = self.lo * b.lo; let lo = low as u64 as Field; let carry = (low - lo) / pow64; let high = if crate::field::modulus_num_bits() as u32 > 196 { - (self.lo+self.hi)*(b.lo+b.hi) - low + carry + (self.lo + self.hi) * (b.lo + b.hi) - low + carry } else { - self.lo*b.hi + self.hi*b.lo + carry + self.lo * b.hi + self.hi * b.lo + carry }; let hi = high as u64 as Field; assert(hi == high, "attempt to multiply with overflow"); - U128 { - lo, - hi, - } + U128 { lo, hi } } } @@ -230,7 +221,7 @@ impl Rem for U128 { let a = b * q + r; assert_eq(self, a); assert(r < b); - + r } } @@ -246,7 +237,7 @@ impl Ord for U128 { fn cmp(self, other: Self) -> Ordering { let hi_ordering = (self.hi as u64).cmp((other.hi as u64)); let lo_ordering = (self.lo as u64).cmp((other.lo as u64)); - + if hi_ordering == Ordering::equal() { lo_ordering } else { @@ -255,16 +246,13 @@ impl Ord for U128 { } } -impl Not for U128 { +impl Not for U128 { fn not(self) -> U128 { - U128 { - lo: (!(self.lo as u64)) as Field, - hi: (!(self.hi as u64)) as Field - } + U128 { lo: (!(self.lo as u64)) as Field, hi: (!(self.hi as u64)) as Field } } } -impl BitOr for U128 { +impl BitOr for U128 { fn bitor(self, other: U128) -> U128 { U128 { lo: ((self.lo as u64) | (other.lo as u64)) as Field, @@ -274,7 +262,7 @@ impl BitOr for U128 { } impl BitAnd for U128 { - fn bitand(self, other: U128) -> U128 { + fn bitand(self, other: U128) -> U128 { U128 { lo: ((self.lo as u64) & (other.lo as u64)) as Field, hi: ((self.hi as u64) & (other.hi as u64)) as Field @@ -283,7 +271,7 @@ impl BitAnd for U128 { } impl BitXor for U128 { - fn bitxor(self, other: U128) -> U128 { + fn bitxor(self, other: U128) -> U128 { U128 { lo: ((self.lo as u64) ^ (other.lo as u64)) as Field, hi: ((self.hi as u64) ^ (other.hi as u64)) as Field @@ -291,36 +279,36 @@ impl BitXor for U128 { } } -impl Shl for U128 { - fn shl(self, other: u8) -> U128 { +impl Shl for U128 { + fn shl(self, other: u8) -> U128 { assert(other < 128, "attempt to shift left with overflow"); let exp_bits: [u1; 7] = (other as Field).to_be_bits(); let mut r: Field = 2; let mut y: Field = 1; for i in 1..8 { - let bit = exp_bits[7-i] as Field; + let bit = exp_bits[7 - i] as Field; y = bit * (r * y) + (1 - bit) * y; r *= r; } self.wrapping_mul(U128::from_integer(y)) - } + } } -impl Shr for U128 { - fn shr(self, other: u8) -> U128 { +impl Shr for U128 { + fn shr(self, other: u8) -> U128 { assert(other < 128, "attempt to shift right with overflow"); let exp_bits: [u1; 7] = (other as Field).to_be_bits(); let mut r: Field = 2; let mut y: Field = 1; for i in 1..8 { - let bit = exp_bits[7-i] as Field; + let bit = exp_bits[7 - i] as Field; y = bit * (r * y) + (1 - bit) * y; r *= r; } self / U128::from_integer(y) - } + } } mod tests { diff --git a/scripts/install_bb.sh b/scripts/install_bb.sh index 015091c07cf..d60c73c0976 100755 --- a/scripts/install_bb.sh +++ b/scripts/install_bb.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="0.51.1" +VERSION="0.55.0" BBUP_PATH=~/.bb/bbup diff --git a/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/Nargo.toml b/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/Nargo.toml new file mode 100644 index 00000000000..8d057a77814 --- /dev/null +++ b/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "arithmetic_generics_move_constant_terms" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/src/main.nr b/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/src/main.nr new file mode 100644 index 00000000000..e27d4baf1f4 --- /dev/null +++ b/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/src/main.nr @@ -0,0 +1,26 @@ +trait FromCallData { + fn from_calldata(calldata: [Field; N]) -> (Self, [Field; M]); +} + +struct Point { x: Field, y: Field } + +impl FromCallData for Field { + fn from_calldata(calldata: [Field; N]) -> (Self, [Field; N - 1]) { + let slice = calldata.as_slice(); + let (value, slice) = slice.pop_front(); + (value, slice.as_array()) + } +} + +impl FromCallData for Point { + fn from_calldata(calldata: [Field; N]) -> (Self, [Field; N - 2]) { + let (x, calldata) = FromCallData::from_calldata(calldata); + let (y, calldata) = FromCallData::from_calldata(calldata); + (Self { x, y }, calldata) + } +} + +fn main() { + let calldata = [1, 2]; + let _: (Point, _) = FromCallData::from_calldata(calldata); +} diff --git a/test_programs/compile_success_empty/attributes_struct/src/main.nr b/test_programs/compile_success_empty/attributes_struct/src/main.nr index 79bf3e29533..669cfc32927 100644 --- a/test_programs/compile_success_empty/attributes_struct/src/main.nr +++ b/test_programs/compile_success_empty/attributes_struct/src/main.nr @@ -9,13 +9,16 @@ fn main() {} // Check that add_attribute and has_named_attribute work well +#[abi(something)] #[add_attribute] struct Foo { } comptime fn add_attribute(s: StructDefinition) { - assert(!s.has_named_attribute(quote { foo })); + assert(!s.has_named_attribute("foo")); s.add_attribute("foo"); - assert(s.has_named_attribute(quote { foo })); + assert(s.has_named_attribute("foo")); + + assert(s.has_named_attribute("abi")); } diff --git a/test_programs/compile_success_empty/comptime_function_definition/src/main.nr b/test_programs/compile_success_empty/comptime_function_definition/src/main.nr index e01ff4a71f1..4266d3734f9 100644 --- a/test_programs/compile_success_empty/comptime_function_definition/src/main.nr +++ b/test_programs/compile_success_empty/comptime_function_definition/src/main.nr @@ -8,6 +8,11 @@ pub fn foo(w: i32, y: Field, Foo { x, field: some_field }: Foo, mut a: bool, (b, 1 } +#[test] +#[deprecated] +#[check_named_attribute] +fn some_test() {} + comptime fn function_attr(f: FunctionDefinition) { // Check FunctionDefinition::parameters let parameters = f.parameters(); @@ -33,7 +38,12 @@ comptime fn function_attr(f: FunctionDefinition) { // Check FunctionDefinition::name assert_eq(f.name(), quote { foo }); - assert(f.has_named_attribute(quote { function_attr })); + assert(f.has_named_attribute("function_attr")); +} + +comptime fn check_named_attribute(f: FunctionDefinition) { + assert(f.has_named_attribute("test")); + assert(f.has_named_attribute("deprecated")); } #[mutate_add_one] diff --git a/test_programs/compile_success_empty/comptime_module/src/main.nr b/test_programs/compile_success_empty/comptime_module/src/main.nr index c3ba7ba4643..9443b59fb0a 100644 --- a/test_programs/compile_success_empty/comptime_module/src/main.nr +++ b/test_programs/compile_success_empty/comptime_module/src/main.nr @@ -3,6 +3,8 @@ mod foo { #![some_attribute] pub fn x() {} pub fn y() {} + + struct Struct1 {} } contract bar {} @@ -74,15 +76,19 @@ fn main() { assert_eq(foo.functions().len(), 2); assert_eq(bar.functions().len(), 0); + // Check Module::structs + assert_eq(foo.structs().len(), 1); + assert_eq(bar.structs().len(), 0); + // Check Module::name assert_eq(foo.name(), quote { foo }); assert_eq(bar.name(), quote { bar }); // Check Module::has_named_attribute - assert(foo.has_named_attribute(quote { some_attribute })); - assert(foo.has_named_attribute(quote { outer_attribute })); - assert(!bar.has_named_attribute(quote { some_attribute })); - assert(another_module.has_named_attribute(quote { some_attribute })); + assert(foo.has_named_attribute("some_attribute")); + assert(foo.has_named_attribute("outer_attribute")); + assert(!bar.has_named_attribute("some_attribute")); + assert(another_module.has_named_attribute("some_attribute")); } assert_eq(counter, 4); diff --git a/test_programs/compile_success_empty/comptime_trait_constraint/src/main.nr b/test_programs/compile_success_empty/comptime_trait_constraint/src/main.nr index 2f2ca89cfb5..448da96a460 100644 --- a/test_programs/compile_success_empty/comptime_trait_constraint/src/main.nr +++ b/test_programs/compile_success_empty/comptime_trait_constraint/src/main.nr @@ -32,7 +32,7 @@ impl Hasher for TestHasher { fn finish(self) -> Field { self.result } - + fn write(&mut self, input: Field) { self.result += input; } diff --git a/test_programs/compile_success_empty/comptime_type/src/main.nr b/test_programs/compile_success_empty/comptime_type/src/main.nr index c9307570c87..c7b3d0b9400 100644 --- a/test_programs/compile_success_empty/comptime_type/src/main.nr +++ b/test_programs/compile_success_empty/comptime_type/src/main.nr @@ -11,9 +11,7 @@ struct StructImplementsSomeTrait { } -impl SomeTrait for StructImplementsSomeTrait { - -} +impl SomeTrait for StructImplementsSomeTrait {} struct StructDoesNotImplementSomeTrait { diff --git a/test_programs/compile_success_empty/inject_context_attribute/src/main.nr b/test_programs/compile_success_empty/inject_context_attribute/src/main.nr index 9dc8cf1ed47..156579ce0b2 100644 --- a/test_programs/compile_success_empty/inject_context_attribute/src/main.nr +++ b/test_programs/compile_success_empty/inject_context_attribute/src/main.nr @@ -45,7 +45,7 @@ comptime fn mapping_function(expr: Expr, f: FunctionDefinition) -> Option let (name, arguments) = func_call; name.resolve(Option::some(f)).as_function_definition().and_then( |function_definition: FunctionDefinition| { - if function_definition.has_named_attribute(quote { inject_context }) { + if function_definition.has_named_attribute("inject_context") { let arguments = arguments.push_front(quote { _context }.as_expr().unwrap()); let arguments = arguments.map(|arg: Expr| arg.quoted()).join(quote { , }); Option::some(quote { $name($arguments) }.as_expr().unwrap()) diff --git a/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr b/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr index 2be1d3fa11e..3ca9c841a8c 100644 --- a/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr +++ b/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr @@ -10,11 +10,15 @@ trait ToField2 { struct Foo { x: Field } impl ToField for Foo { - fn to_field(self) -> Field { self.x } + fn to_field(self) -> Field { + self.x + } } impl ToField2 for Foo { - fn to_field(self) -> Field { self.x } + fn to_field(self) -> Field { + self.x + } } impl Foo { diff --git a/test_programs/compile_success_empty/regression_4635/src/main.nr b/test_programs/compile_success_empty/regression_4635/src/main.nr index 75188f797dd..6709a421470 100644 --- a/test_programs/compile_success_empty/regression_4635/src/main.nr +++ b/test_programs/compile_success_empty/regression_4635/src/main.nr @@ -44,7 +44,7 @@ struct MyStruct { impl Deserialize<1> for MyStruct where T: FromField { fn deserialize(fields: [Field; 1]) -> Self { - Self{ a: FromField::from_field(fields[0]) } + Self { a: FromField::from_field(fields[0]) } } } diff --git a/test_programs/compile_success_empty/serialize/src/main.nr b/test_programs/compile_success_empty/serialize/src/main.nr index 79114c5b567..6fee6fb72a6 100644 --- a/test_programs/compile_success_empty/serialize/src/main.nr +++ b/test_programs/compile_success_empty/serialize/src/main.nr @@ -14,10 +14,10 @@ impl Serialize for (A, B) where A: Serialize Serialize for [T; N] where T: Serialize Self { - Self { bar: x, array: [x,y] } + fn my_default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x, y] } } } diff --git a/test_programs/compile_success_empty/trait_function_calls/src/main.nr b/test_programs/compile_success_empty/trait_function_calls/src/main.nr index 39d28a5a3b3..62af0e756cd 100644 --- a/test_programs/compile_success_empty/trait_function_calls/src/main.nr +++ b/test_programs/compile_success_empty/trait_function_calls/src/main.nr @@ -30,7 +30,7 @@ trait Trait1a { } } struct Struct1a { vl: Field } -impl Trait1a for Struct1a { } +impl Trait1a for Struct1a {} // 1b) trait default method -> trait overriden method trait Trait1b { fn trait_method1(self) -> Field { @@ -162,7 +162,7 @@ trait Trait2a { } } struct Struct2a { vl: Field } -impl Trait2a for Struct2a { } +impl Trait2a for Struct2a {} // 2b) trait default method -> trait overriden function trait Trait2b { fn trait_method1(self) -> Field { @@ -294,7 +294,7 @@ trait Trait3a { } } struct Struct3a { vl: Field } -impl Trait3a for Struct3a { } +impl Trait3a for Struct3a {} // 3b) trait default function -> trait overriden method trait Trait3b { fn trait_function1(a: Field, b: Self) -> Field { @@ -426,7 +426,7 @@ trait Trait4a { } } struct Struct4a { vl: Field } -impl Trait4a for Struct4a { } +impl Trait4a for Struct4a {} // 4b) trait default function -> trait overriden function trait Trait4b { fn trait_function1() -> Field { diff --git a/test_programs/compile_success_empty/trait_impl_generics/src/main.nr b/test_programs/compile_success_empty/trait_impl_generics/src/main.nr index c46c41cbdd7..bae4d62f9e4 100644 --- a/test_programs/compile_success_empty/trait_impl_generics/src/main.nr +++ b/test_programs/compile_success_empty/trait_impl_generics/src/main.nr @@ -5,11 +5,15 @@ trait Foo { } impl Foo for Empty { - fn foo(_self: Self) -> u32 { 32 } + fn foo(_self: Self) -> u32 { + 32 + } } impl Foo for Empty { - fn foo(_self: Self) -> u32 { 64 } + fn foo(_self: Self) -> u32 { + 64 + } } fn main() { @@ -43,7 +47,9 @@ trait T2 { struct S2 { x: T } impl T2 for S2 { - fn t2(self) -> Self { self } + fn t2(self) -> Self { + self + } } fn call_impl_with_generic_function() { @@ -55,5 +61,7 @@ trait T3 { } impl T3 for u32 { - fn t3(_self: Self, y: U) -> U { y } + fn t3(_self: Self, y: U) -> U { + y + } } diff --git a/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr b/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr index 780512f04dc..6da2c86fa2f 100644 --- a/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr +++ b/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr @@ -13,7 +13,7 @@ trait MyEq { impl MyEq for [T; 3] where T: MyEq { fn my_eq(self, other: Self) -> bool { let mut ret = true; - for i in 0 .. self.len() { + for i in 0..self.len() { ret &= self[i].my_eq(other[i]); } ret diff --git a/test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr index 35f5ce3a183..cb4eb3a2956 100644 --- a/test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr +++ b/test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr @@ -1,2 +1,2 @@ // ensure we can implement traits using the Path syntax -impl crate::module4::MyTrait4 for crate::module5::MyStruct5 { } +impl crate::module4::MyTrait4 for crate::module5::MyStruct5 {} diff --git a/test_programs/compile_success_empty/trait_override_implementation/src/main.nr b/test_programs/compile_success_empty/trait_override_implementation/src/main.nr index 21d89b1b261..68a928c0c52 100644 --- a/test_programs/compile_success_empty/trait_override_implementation/src/main.nr +++ b/test_programs/compile_success_empty/trait_override_implementation/src/main.nr @@ -12,8 +12,8 @@ struct Foo { } impl MyDefault for Foo { - fn my_default(x: Field,y: Field) -> Self { - Self { bar: x, array: [x,y] } + fn my_default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x, y] } } fn method2(x: Field) -> Field { @@ -32,9 +32,15 @@ trait F { struct Bar {} impl F for Bar { - fn f5(_self: Self) -> Field { 50 } - fn f1(_self: Self) -> Field { 10 } - fn f3(_self: Self) -> Field { 30 } + fn f5(_self: Self) -> Field { + 50 + } + fn f1(_self: Self) -> Field { + 10 + } + fn f3(_self: Self) -> Field { + 30 + } } // Impls on mutable references are temporarily disabled // impl F for &mut Bar { diff --git a/test_programs/compile_success_empty/trait_static_methods/src/main.nr b/test_programs/compile_success_empty/trait_static_methods/src/main.nr index 838e47ee82e..976d0ab762c 100644 --- a/test_programs/compile_success_empty/trait_static_methods/src/main.nr +++ b/test_programs/compile_success_empty/trait_static_methods/src/main.nr @@ -16,7 +16,7 @@ struct Foo { impl ATrait for Foo { fn asd() -> Self { // This should pass as Self should be bound to Foo while typechecking this - Foo{x: 100} + Foo { x: 100 } } } @@ -27,7 +27,7 @@ impl ATrait for Bar { // The trait method is declared as returning `Self` // but explicitly specifying the type in the impl should work fn asd() -> Bar { - Bar{x: 100} + Bar { x: 100 } } fn static_method_2() -> Field { diff --git a/test_programs/compile_success_empty/trait_where_clause/src/main.nr b/test_programs/compile_success_empty/trait_where_clause/src/main.nr index 5fd7e78abf4..655450d05ac 100644 --- a/test_programs/compile_success_empty/trait_where_clause/src/main.nr +++ b/test_programs/compile_success_empty/trait_where_clause/src/main.nr @@ -12,9 +12,21 @@ struct Add20 { x: Field, } struct Add30 { x: Field, } struct AddXY { x: Field, y: Field, } -impl Asd for Add10 { fn asd(self) -> Field { self.x + 10 } } -impl Asd for Add20 { fn asd(self) -> Field { self.x + 20 } } -impl Asd for Add30 { fn asd(self) -> Field { self.x + 30 } } +impl Asd for Add10 { + fn asd(self) -> Field { + self.x + 10 + } +} +impl Asd for Add20 { + fn asd(self) -> Field { + self.x + 20 + } +} +impl Asd for Add30 { + fn asd(self) -> Field { + self.x + 30 + } +} impl Asd for AddXY { fn asd(self) -> Field { @@ -29,7 +41,9 @@ impl StaticTrait for Static100 { struct Static200 {} impl StaticTrait for Static200 { - fn static_function(slf: Self) -> Field { 200 } + fn static_function(slf: Self) -> Field { + 200 + } } fn assert_asd_eq_100(t: T) where T: crate::the_trait::Asd { diff --git a/test_programs/compile_success_empty/traits/src/main.nr b/test_programs/compile_success_empty/traits/src/main.nr index 0a5644e7530..9ef0ec6aba9 100644 --- a/test_programs/compile_success_empty/traits/src/main.nr +++ b/test_programs/compile_success_empty/traits/src/main.nr @@ -8,8 +8,8 @@ struct Foo { } impl MyDefault for Foo { - fn my_default(x: Field,y: Field) -> Self { - Self { bar: x, array: [x,y] } + fn my_default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x, y] } } } diff --git a/test_programs/execution_success/bench_2_to_17/Nargo.toml b/test_programs/execution_success/bench_2_to_17/Nargo.toml new file mode 100644 index 00000000000..47f49530483 --- /dev/null +++ b/test_programs/execution_success/bench_2_to_17/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_2_to_17" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/bench_2_to_17/Prover.toml b/test_programs/execution_success/bench_2_to_17/Prover.toml new file mode 100644 index 00000000000..2d35b0614e3 --- /dev/null +++ b/test_programs/execution_success/bench_2_to_17/Prover.toml @@ -0,0 +1 @@ +x = "3" \ No newline at end of file diff --git a/test_programs/execution_success/bench_2_to_17/src/main.nr b/test_programs/execution_success/bench_2_to_17/src/main.nr new file mode 100644 index 00000000000..ae80dfcf0b4 --- /dev/null +++ b/test_programs/execution_success/bench_2_to_17/src/main.nr @@ -0,0 +1,8 @@ +use std::hash::poseidon2; + +global len = 2450 * 2; +fn main(x: Field) { + let ped_input = [x; len]; + let mut val = poseidon2::Poseidon2::hash(ped_input, len); + assert(val != 0); +} diff --git a/test_programs/execution_success/derive/src/main.nr b/test_programs/execution_success/derive/src/main.nr index b32612831d7..f2f467eb761 100644 --- a/test_programs/execution_success/derive/src/main.nr +++ b/test_programs/execution_success/derive/src/main.nr @@ -69,7 +69,7 @@ impl std::hash::Hasher for TestHasher { fn finish(self) -> Field { self.result } - + fn write(&mut self, input: Field) { self.result += input; } diff --git a/test_programs/execution_success/fold_2_to_17/Nargo.toml b/test_programs/execution_success/fold_2_to_17/Nargo.toml new file mode 100644 index 00000000000..54e4c9a64e8 --- /dev/null +++ b/test_programs/execution_success/fold_2_to_17/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_2_to_17" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/fold_2_to_17/Prover.toml b/test_programs/execution_success/fold_2_to_17/Prover.toml new file mode 100644 index 00000000000..a56a84e61a4 --- /dev/null +++ b/test_programs/execution_success/fold_2_to_17/Prover.toml @@ -0,0 +1 @@ +x = "2" diff --git a/test_programs/execution_success/fold_2_to_17/src/main.nr b/test_programs/execution_success/fold_2_to_17/src/main.nr new file mode 100644 index 00000000000..a3a747e4aee --- /dev/null +++ b/test_programs/execution_success/fold_2_to_17/src/main.nr @@ -0,0 +1,16 @@ +use std::hash::poseidon2; + +global len = 2450 * 2 - 240; // for just under 2^17 gates +fn main(x: Field) { + let ped_input = [x; len]; + let mut val = poseidon2::Poseidon2::hash(ped_input, len); + let z = foo(x); + assert(val == z); +} + +#[fold] +fn foo(x: Field) -> Field { + let ped_input = [x; len]; + let mut val = poseidon2::Poseidon2::hash(ped_input, len); + val +} diff --git a/test_programs/execution_success/single_verify_proof/Nargo.toml b/test_programs/execution_success/single_verify_proof/Nargo.toml new file mode 100644 index 00000000000..9dfbbcb9c1d --- /dev/null +++ b/test_programs/execution_success/single_verify_proof/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "single_verify_proof" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/single_verify_proof/Prover.toml b/test_programs/execution_success/single_verify_proof/Prover.toml new file mode 100644 index 00000000000..27b3ebc0c35 --- /dev/null +++ b/test_programs/execution_success/single_verify_proof/Prover.toml @@ -0,0 +1,4 @@ +key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" +proof = ["0x000000000000000000000000000000d62b795bec274279129a71195796825fcc","0x00000000000000000000000000000000000793ab763140f20a68a6bd2721fd74","0x00000000000000000000000000000053141d06d3307b36153f321511199e579c","0x00000000000000000000000000000000000a4b55d6c21f98a9c434911dcb5c67","0x0000000000000000000000000000005f9d324c0abd22cec92d99dbec438e9491","0x0000000000000000000000000000000000240dfafe1b53dc27147cbab14ea893","0x000000000000000000000000000000044a61d3aac32c6931247cf334a19d9611","0x000000000000000000000000000000000003f0f8cf4207bfa85c23ec9f8d0c88","0x00000000000000000000000000000002168a470e39ba2ac266f6b474de12045f","0x000000000000000000000000000000000025791e7d3feab542345c00ec5a30df","0x000000000000000000000000000000dcafd76d4c3640969c80e017b951ef6397","0x00000000000000000000000000000000001d27f75a1256771e88e0c86fc42dbc","0x0000000000000000000000000000007347ae7d2d9d7fc2b8f0baa014ee1fed9f","0x000000000000000000000000000000000018bd927f42bf7caf9555f56f09000d","0x000000000000000000000000000000041f765f83cbe5904c8f453f70a4531d10","0x00000000000000000000000000000000001858aabeeb5331a221419f4fed1c19","0x000000000000000000000000000000d254a54caaedf8287b9af951b2f2611121","0x000000000000000000000000000000000005ab493623c9563cf2e55ba5f18200","0x00000000000000000000000000000014f24cddc1a02440dc63637df8032c8074","0x000000000000000000000000000000000011950c16cef98471b1d78b935195a4","0x000000000000000000000000000000b0340b459e6bd5cc8f031c8654a502897f","0x00000000000000000000000000000000000e1cf3968dac4545a76a2ae58e512c","0x0000000000000000000000000000002adf7218aa06ca0d2c2e600dcc39193a2d","0x00000000000000000000000000000000001302e7e4b0f14749bd885ca25588b6","0x00000000000000000000000000000092009ce4056e79ab815d8cdfd4491138ae","0x000000000000000000000000000000000018af11e853c6cf2f0f6274b0da8133","0x000000000000000000000000000000dd3dc6f49232141718527b3a0e4b26e21d","0x00000000000000000000000000000000001a877853348a8b695c4f9a9aa4ce68","0x000000000000000000000000000000aecfc56ba07155450b368140d6324023b5","0x000000000000000000000000000000000029c11052798c57ece614617d33fcc2","0x000000000000000000000000000000eb106ffc816d16fb84e84b0b61157b2603","0x000000000000000000000000000000000026c3cac16206899a21cb5126841446","0x000000000000000000000000000000a782ed54805fe845068b362b58e2fa34ec","0x00000000000000000000000000000000000cf046a1bfcc666b7f28b572676073","0x000000000000000000000000000000b931c8dda60bb4aca4cc817f5540f1209f","0x000000000000000000000000000000000024ad50c3936fafc3d190e6a4874223","0x000000000000000000000000000000cce90cfbaf5671c8c8652db28a3a9566f7","0x000000000000000000000000000000000003574db9d0f84380c9635660f86354","0x0000000000000000000000000000003eb3e1dc31846a90f721e7a08c6d6dc4f7","0x000000000000000000000000000000000028999a700cd1abae1a288eebb9a91c","0x000000000000000000000000000000c1be4d385b11387e14eb9817050d772f78","0x000000000000000000000000000000000003c56b5bad8b4484c66ac921f1f102","0x000000000000000000000000000000ace245cabf0f00dc7fd253dd8af0377a14","0x0000000000000000000000000000000000107f1731fcf34b364c813599fa1df7","0x035b937d404932b542b706eb810ef4a7dca4566d4dde1ad6a8717f46167ead7e","0x17608cef3dc7960f41cb1295706df663727d45ee598a61e05e989d111449fb65","0x054712a950ad67da3aa860e49e6891f99b586b7f37caff94eb013fdb374b61ee","0x04b755083086c769b7f593e0e48d68dc54be808203351380ca5566a48149d8bb","0x17d7670b0915235f626fdc1d7e1134d2be906ef138d7843384b3ebc23b1d630f","0x064cf544ab5f4e3dab47960502cccc83321fb275068dfbdd3a2fcbc6dddcaa65","0x083338262712e2b66769ea40d9f412b18caa1bc81a51ff5a50b6c41f8c4b3d23","0x0cdd38958cab97defde00f4a5961b6fd676e29d9f2c352f6bb2c68b91f83f8af","0x02c8bdd005c2f43a0a8cbb2744916ce5c322dfa5b23367a829c12699f4036d32","0x25bac73c7e7b659fbea3135b7a0decf9db8dc3045bd2837dae337c64cc722546","0x19eb361aa419d37bce3d2e8b2b7692a02a9559e83d7f3d8fe9169970fbbc2cba","0x2494bd5106d00e05c7ea60e632e9fe03773b7f2c5b662aa37ec512a01f4a0775","0x18c52c2f2c6e7be1d7847c15e452a3a9c64316103d12e4b5b9a82fac4e940ee9","0x0e0342810456ef78f498c1bfa085a5f3cbc06db1f32fabd0ea9ad27dccac1680","0x024c13d6ef56af33ed7164ea8e47ddecc8a487b000d8b1b45edcd3895a503ba2","0x26e0d127f626bd39b55bc5d0c131dbf03fe006dc5c3edc57dda1e629799a4317","0x1b1140061bc52b15c4f5e100729a81968ee79dc03deb966a18850335a8e44a8b","0x1bb76f945199e71d531a89288912087a02dd0e83020e65d671485bf2e5e86e1a","0x29269900859c6d86e404185b415bf3b279cd100f38cfdb0077e8d6a299c4fd35","0x22b5e94bae2f6f0cdb424a3b12c4bf82cec3fb228e012c1974ed457827bbe012","0x18d3543a93249778e7a57936170dae85ffc47c2567f2d0076a32c0bb86fcf10a","0x03721dc2670206cde42a175fd56bcce32cf6cb8801450a8e8e4b3d4e07785973","0x2806db136dd214d3ac1478460855cae6a4324ab45cab35320d104fee26c260e8","0x1c3749f1937082afbbae9375b9be708cf339e1983e57ef4447f36cfa560c685c","0x1067b8cfb90ef08bcb48aea56b2716334241787c2004a95682d68a0685566fd0","0x0f41aee4416398f1d48ffc302403273cddef34a41f98507c53682041d82e51ff","0x10d854c9f0bfbdff7ca91a68f4978e9a79e7b14243d92f465f17bdf88d9f64f8","0x00000000000000000000000000000000018938b11099e0cdc05ddab84a153a97","0x0000000000000000000000000000000001d7dda1471f0dc3b3a3d3438c197982","0x00000000000000000000000000000000022682917da43ab9a6e9cbcece1db86d","0x2453913e6b0f36eab883ac4b0e0604d56aaeb9c55e641135173e63c342f1a660","0x05216c1b58dc43a49d01aaba3113b0e86be450fc17d28016e648e7162a1b67fb","0x152b34845a0222a2b41354c0d395a250d8363dc18748647d85acd89d6934ec56","0x1dfc6e971ce82b7dcda1f7f282713c6e22a8c79258a61209bda69719806da544","0x2968dd8b3af8e3953f1fbbd72f4c49b8270597bb27d4037adc157ac6083bee60","0x1b9425b88a4c7d39b3d75afe66917a9aa1d2055724392bc01fb918d84ff1410e","0x04ab571f236d8e750904dc307dd274003d9130f1a7110e4c1521cfb408877c73","0x2ad84f26fdc5831545272d02b806bb0e6dae44e71f73552c4eb9ff06030748c7","0x020e632b99d325db774b8630fb50b9a4e74d35b7f27d9fc02c65087ee747e42c","0x09a8c5a3171268cb61c02515c01c109889200ed13f415ae54df2078bbb887f92","0x1143281a9451abbb4c34c3fa84e7678c2af2e7ea8c05160a6f7f06988fc91af8","0x000000000000000000000000000000cbda736ca5cf6bc75413c2cc9e28ab0a68","0x00000000000000000000000000000000001ee78c9cc56aa5991062ae2e338587","0x000000000000000000000000000000bc9bfcdebb486f4cb314e681d2cc5f8df6","0x00000000000000000000000000000000000ad538431d04771bca7f633cb659ff","0x000000000000000000000000000000d45b317afcefa466a59bba9e171f1af70c","0x0000000000000000000000000000000000133c50180ea17932e4881124e7a7c6","0x000000000000000000000000000000fc9ed37f543775849f3e84eaa06f77f992","0x00000000000000000000000000000000001372873c9c051d1baff99248b8f70e"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x2b337de1c8c14f22ec9b9e2f96afef3652627366f8170a0a948dad4ac1bd5e80","0x0000000000000000000000000000000000000000000000000000000000000008","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000000000092139c61bae1a44f0fc7689507414be688","0x00000000000000000000000000000000000160ce4e279582f91bde4f03f5e9a2","0x0000000000000000000000000000005dc2d37f658c3b2d60f24740eb13b65d79","0x000000000000000000000000000000000007e3e8a5d98a1177ec85bf88f163a5","0x000000000000000000000000000000dc3035fbd7ff16412a8fd7da587a935298","0x000000000000000000000000000000000023d08e2817ac16990004ed11d8fc66","0x000000000000000000000000000000356a5ad59c646c746a8d09f5d154e47c4f","0x00000000000000000000000000000000000708529196af3c8e16ffa580c26182","0x0000000000000000000000000000002ddfe70eb7a1280596e8e4a804f118a6dd","0x000000000000000000000000000000000013757e15a0905f298303784a161b21","0x000000000000000000000000000000a23a729df796935c7824e3a26be794829b","0x000000000000000000000000000000000005775b6c146c4a59856e869fe5a70e","0x000000000000000000000000000000eef0c9e088fd2d45aa40311082d1f2809b","0x00000000000000000000000000000000001d539ccbfc556d0ad59307a218de65","0x000000000000000000000000000000a2c848beceb6ab7806fd3b88037b8410fc","0x0000000000000000000000000000000000177004deeb1f9d401fd7b1af1a5ac8","0x0000000000000000000000000000002508eb63672a733f20de1a97644be4f540","0x00000000000000000000000000000000000d82d51f2f75d806285fd248c819b8","0x000000000000000000000000000000d002f9100cbba8a29f13b11513c53c59d0","0x000000000000000000000000000000000006cd3b0e3460533b9e5ea2cdc0fcbb","0x000000000000000000000000000000f45ea38a93b2f810c5633ddb54927c1c96","0x000000000000000000000000000000000021791de65f9a28ec7024b1a87ab4f3","0x000000000000000000000000000000926511a0439502c86885a8c6f0327aa7ad","0x000000000000000000000000000000000029fa14a969c5d81ed3abbbfb11220a","0x000000000000000000000000000000b84c3258e8206f560e5b5b18cbeafef87e","0x00000000000000000000000000000000002a910445cd8fc895e5d235cd8ea185","0x000000000000000000000000000000887e67f15e84bcb8507a5064a363f6043b","0x000000000000000000000000000000000014dc6643d801c3ef27c2066b6e2bb4","0x000000000000000000000000000000e38e900b42c314ba803088e8fbf125203f","0x000000000000000000000000000000000020690fd4869db418306046b38161dc","0x0000000000000000000000000000001e2fa856bf7951b8292b1e88185993629c","0x0000000000000000000000000000000000048a85e0bbac7c60ad3d78f601f63c","0x0000000000000000000000000000006f457719495073d3666d77a625aeab0c51","0x00000000000000000000000000000000002623ad892dc62b1fa7d0a650f0d470","0x000000000000000000000000000000dbfcc8a467e021c03b13f74a9f79c3a10c","0x0000000000000000000000000000000000295f6f10976c37bd9c6f96bb7187d5","0x000000000000000000000000000000c13ef9a937cc12420fb38d9ab8e848e85e","0x000000000000000000000000000000000003560a3b334e887532f605c9cb7628","0x0000000000000000000000000000009bcebf08a4599cdda0fb96312d4dc0c7a9","0x000000000000000000000000000000000015adc8bb1e01c835f48959d1237bd6","0x00000000000000000000000000000047762ab839e4ff63c77605a9f383da37c2","0x000000000000000000000000000000000016a8c3c53d89660cf271522cd301fb","0x000000000000000000000000000000f0c8539a0b5f94420a513f9c305b932bfe","0x00000000000000000000000000000000002957ba01d9de5638f808f88a692533","0x000000000000000000000000000000ab17c6189d67d3bf5dd2f3885de0151b6f","0x0000000000000000000000000000000000060d8aa43fdc434d1942263f364d95","0x0000000000000000000000000000005d292333b3adb497f00b4bc32d45229060","0x00000000000000000000000000000000001a1018a66221883639f2898a66f345","0x00000000000000000000000000000006555a806b1993291deba0dc44e2abf431","0x00000000000000000000000000000000000cacff7099a9d5e35a21f4a00b2dc3","0x000000000000000000000000000000f50c11ba95d349c36d143eefd12e494950","0x00000000000000000000000000000000001022e8c5f02d639bc9dd8bc4407f99","0x000000000000000000000000000000c76828795098eda73d50b4b585c60afc60","0x00000000000000000000000000000000002bf09c0ec7011e93888962f2406630","0x00000000000000000000000000000049e5c83a8978d832fb8e144548e3ca1adb","0x00000000000000000000000000000000000e0ec242c2e160a984f61ca5adf5f5","0x0000000000000000000000000000009c5d6e08a6605ab4513748ac0fa017dd1c","0x00000000000000000000000000000000001f54baa07558e5fb055bd9ba49c067","0x0000000000000000000000000000001e1ee7ee29bbb5e4b080c6091c1433ce62","0x000000000000000000000000000000000024aec62a9d9763499267dc98c33428","0x0000000000000000000000000000001a96755946ff16f0d6632365f0eb0ab4d4","0x000000000000000000000000000000000028cf3e22bcd53782ebc3e0490e27e5","0x00000000000000000000000000000043148d7d8c9ba43f2133fab4201435a364","0x0000000000000000000000000000000000234ce541f1f5117dd404cfaf01a229","0x000000000000000000000000000000a7fb95ffb461d9514a1070e2d2403982ef","0x00000000000000000000000000000000003016955028b6390f446c3fd0c5b424","0x00000000000000000000000000000008863c3b7cd7cddc20ba79ce915051c56e","0x000000000000000000000000000000000013ef666111b0be56a235983d397d2a","0x000000000000000000000000000000e3993f465fc9f56e93ac769e597b752c1c","0x0000000000000000000000000000000000217f7c4235161e9a3c16c45b6ca499","0x0000000000000000000000000000008ffa4cd96bc67b0b7df5678271e1114075","0x0000000000000000000000000000000000256467bfcb63d9fdcb5dde397757ad","0x00000000000000000000000000000054e5eb270bb64bde6e6ececadfd8c3236c","0x00000000000000000000000000000000000e52d1bd75812c33c6f3d79ee4b94c","0x000000000000000000000000000000484a2c641dce55bc2dd64ef0cd790a7fea","0x00000000000000000000000000000000000ff417d256be43e73c8b1aa85bdda3","0x0000000000000000000000000000000b72e7b7713ab5da44e0f864182e748a23","0x00000000000000000000000000000000001a221055f1625ad833a44705f5f74e","0x00000000000000000000000000000067a99a34e9b81a17ad001db02e29bcb82a","0x000000000000000000000000000000000018a6c02e398389827568fa960e86e2","0x000000000000000000000000000000bb29f26f9890d6cc6401f4921d5884edca","0x00000000000000000000000000000000000868357b28039385c5a5058b6d358e","0x00000000000000000000000000000036fb6e229dde8edf7ec858b12d7e8be485","0x00000000000000000000000000000000001060afe929554ca473103f5e68193c","0x00000000000000000000000000000015226e07e207744c0857074dcab883af4a","0x00000000000000000000000000000000000b1c02619282755533457230b19b4a","0x0000000000000000000000000000001f2a0277e4807e6e1cbabca21dde5eb5e1","0x00000000000000000000000000000000000d928deafed363659688ed4ccdef52","0x000000000000000000000000000000363f0c994e91cecad25835338edee2294f","0x00000000000000000000000000000000002eea648c8732596b1314fe2a4d2f05","0x000000000000000000000000000000b2671d2ae51d31c1210433c3972bb64578","0x00000000000000000000000000000000000ab49886c2b94bd0bd3f6ed1dbbe2c"] \ No newline at end of file diff --git a/test_programs/execution_success/single_verify_proof/src/main.nr b/test_programs/execution_success/single_verify_proof/src/main.nr new file mode 100644 index 00000000000..4eb0cfdf6d0 --- /dev/null +++ b/test_programs/execution_success/single_verify_proof/src/main.nr @@ -0,0 +1,15 @@ + +// This circuit aggregates one proof from `assert_statement_recursive`. +fn main( + verification_key: [Field; 114], + // This is the proof without public inputs attached. + // + // This means: the size of this does not change with the number of public inputs. + proof: [Field; 93], + public_inputs: pub [Field; 1], + // This is currently not public. It is fine given that the vk is a part of the circuit definition. + // I believe we want to eventually make it public too though. + key_hash: Field +) { + std::verify_proof(verification_key, proof, public_inputs, key_hash); +} diff --git a/test_programs/execution_success/slice_regex/src/main.nr b/test_programs/execution_success/slice_regex/src/main.nr index 2382f5b0f2f..15768248473 100644 --- a/test_programs/execution_success/slice_regex/src/main.nr +++ b/test_programs/execution_success/slice_regex/src/main.nr @@ -12,9 +12,8 @@ impl Match { impl Eq for Match { fn eq(self, other: Self) -> bool { - (self.succeeded == other.succeeded) & - (self.match_ends == other.match_ends) - // (self.leftover == other.leftover) + (self.succeeded == other.succeeded) & (self.match_ends == other.match_ends) + // (self.leftover == other.leftover) } } @@ -48,17 +47,9 @@ impl Regex for str { } } if matches_input { - Match { - succeeded: true, - match_ends: self_as_bytes.len(), - leftover, - } + Match { succeeded: true, match_ends: self_as_bytes.len(), leftover } } else { - Match { - succeeded: false, - match_ends: 0, - leftover: input, - } + Match { succeeded: false, match_ends: 0, leftover: input } } } } @@ -73,21 +64,13 @@ impl Regex for (T, U) where T: Regex, U: Regex { Match { succeeded: true, match_ends: lhs_result.match_ends + rhs_result.match_ends, - leftover: rhs_result.leftover, + leftover: rhs_result.leftover } } else { - Match { - succeeded: false, - match_ends: 0, - leftover: input, - } + Match { succeeded: false, match_ends: 0, leftover: input } } } else { - Match { - succeeded: false, - match_ends: 0, - leftover: input, - } + Match { succeeded: false, match_ends: 0, leftover: input } } } } @@ -136,10 +119,7 @@ struct Question { impl Regex for Question where T: Regex { fn match(self, input: [u8]) -> Match { - Or { - lhs: self.inner, - rhs: (), - }.match(input) + Or { lhs: self.inner, rhs: () }.match(input) } } @@ -150,9 +130,7 @@ struct Star { impl Regex for Star where T: Regex { fn match(self, input: [u8]) -> Match { - let regex: Repeated<_, N> = Repeated { - inner: Question { inner: self.inner }, - }; + let regex: Repeated<_, N> = Repeated { inner: Question { inner: self.inner } }; regex.match(input) } } @@ -166,10 +144,7 @@ impl Regex for Plus where T: Regex fn match(self, input: [u8]) -> Match { std::static_assert(N_PRED + 1 == N, "N - 1 != N_PRED"); let star: Star = Star { inner: self.inner }; - ( - self.inner, - star - ).match(input) + (self.inner, star).match(input) } } diff --git a/test_programs/execution_success/trait_impl_base_type/src/main.nr b/test_programs/execution_success/trait_impl_base_type/src/main.nr index bb11dcab73a..e12cf019e0b 100644 --- a/test_programs/execution_success/trait_impl_base_type/src/main.nr +++ b/test_programs/execution_success/trait_impl_base_type/src/main.nr @@ -5,7 +5,7 @@ trait Fieldable { impl Fieldable for u32 { fn to_field(self) -> Field { let res = self as Field; - res * 3 + res * 3 } } @@ -18,21 +18,13 @@ impl Fieldable for [u32; 3] { impl Fieldable for bool { fn to_field(self) -> Field { - if self { - 14 - } else { - 3 - } + if self { 14 } else { 3 } } } impl Fieldable for (u32, bool) { fn to_field(self) -> Field { - if self.1 { - self.0 as Field - } else { - 32 - } + if self.1 { self.0 as Field } else { 32 } } } diff --git a/test_programs/rebuild.sh b/test_programs/rebuild.sh index 1f2e199e814..e5badbd2ea6 100755 --- a/test_programs/rebuild.sh +++ b/test_programs/rebuild.sh @@ -28,16 +28,17 @@ process_dir() { fi if ! nargo execute witness; then - echo "$dir: failed" + echo "$dir failed" else if [ -d "$current_dir/acir_artifacts/$dir_name/target" ]; then rm -r "$current_dir/acir_artifacts/$dir_name/target" fi mkdir "$current_dir/acir_artifacts/$dir_name/target" + mkdir "$current_dir/acir_artifacts/$dir_name/proofs" mv ./target/$dir_name.json "$current_dir/acir_artifacts/$dir_name/target/program.json" mv ./target/*.gz "$current_dir/acir_artifacts/$dir_name/target/" - echo "$dir: succeeded" + echo "$dir succeeded" fi cd "$current_dir" diff --git a/tooling/fuzzer/src/dictionary/mod.rs b/tooling/fuzzer/src/dictionary/mod.rs index 942462c4f37..e10da8cc54a 100644 --- a/tooling/fuzzer/src/dictionary/mod.rs +++ b/tooling/fuzzer/src/dictionary/mod.rs @@ -10,7 +10,7 @@ use acvm::{ circuit::{ brillig::{BrilligBytecode, BrilligInputs}, directives::Directive, - opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput}, + opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum}, Circuit, Opcode, Program, }, native_types::Expression, @@ -83,21 +83,24 @@ fn build_dictionary_from_circuit(circuit: &Circuit) -> HashSet< } } - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { input: ConstantOrWitnessEnum::Constant(c), num_bits }, - }) => { - let field = 1u128.wrapping_shl(*num_bits); - constants.insert(F::from(field)); - constants.insert(F::from(field - 1)); - constants.insert(*c); - } - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput { input: ConstantOrWitnessEnum::Witness(_), num_bits }, - }) => { - let field = 1u128.wrapping_shl(*num_bits); - constants.insert(F::from(field)); - constants.insert(F::from(field - 1)); + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) + if matches!(input.input(), ConstantOrWitnessEnum::Constant(..)) => + { + match input.input() { + ConstantOrWitnessEnum::Constant(c) => { + let field = 1u128.wrapping_shl(input.num_bits()); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + constants.insert(c); + } + _ => { + let field = 1u128.wrapping_shl(input.num_bits()); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + } + } } + _ => (), } } diff --git a/tooling/lsp/src/modules.rs b/tooling/lsp/src/modules.rs index cce7f324a2e..c8f7430c997 100644 --- a/tooling/lsp/src/modules.rs +++ b/tooling/lsp/src/modules.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use noirc_frontend::{ ast::ItemVisibility, - graph::CrateId, + graph::{CrateId, Dependency}, hir::def_map::{CrateDefMap, ModuleId}, macros_api::{ModuleDefId, NodeInterner}, node_interner::ReferenceId, @@ -41,7 +41,7 @@ pub(crate) fn module_def_id_to_reference_id(module_def_id: ModuleDefId) -> Refer /// Returns the fully-qualified path of the given `ModuleDefId` relative to `current_module_id`: /// - If `ModuleDefId` is a module, that module's path is returned /// - Otherwise, that item's parent module's path is returned -pub(crate) fn module_full_path( +pub(crate) fn relative_module_full_path( module_def_id: ModuleDefId, visibility: ItemVisibility, current_module_id: ModuleId, @@ -55,8 +55,12 @@ pub(crate) fn module_full_path( return None; } - full_path = - module_id_path(module_id, ¤t_module_id, current_module_parent_id, interner); + full_path = relative_module_id_path( + module_id, + ¤t_module_id, + current_module_parent_id, + interner, + ); } else { let Some(parent_module) = get_parent_module(interner, module_def_id) else { return None; @@ -66,15 +70,19 @@ pub(crate) fn module_full_path( return None; } - full_path = - module_id_path(parent_module, ¤t_module_id, current_module_parent_id, interner); + full_path = relative_module_id_path( + parent_module, + ¤t_module_id, + current_module_parent_id, + interner, + ); } Some(full_path) } /// Returns the path to reach an item inside `target_module_id` from inside `current_module_id`. /// Returns a relative path if possible. -pub(crate) fn module_id_path( +pub(crate) fn relative_module_id_path( target_module_id: ModuleId, current_module_id: &ModuleId, current_module_parent_id: Option, @@ -130,3 +138,52 @@ pub(crate) fn module_id_path( segments.reverse(); segments.join("::") } + +pub(crate) fn module_full_path( + module: &ModuleId, + interner: &NodeInterner, + crate_id: CrateId, + crate_name: &str, + dependencies: &Vec, +) -> String { + let mut segments: Vec = Vec::new(); + + if let Some(module_attributes) = interner.try_module_attributes(module) { + segments.push(module_attributes.name.clone()); + + let mut current_attributes = module_attributes; + loop { + let Some(parent_local_id) = current_attributes.parent else { + break; + }; + + let Some(parent_attributes) = interner.try_module_attributes(&ModuleId { + krate: module.krate, + local_id: parent_local_id, + }) else { + break; + }; + + segments.push(parent_attributes.name.clone()); + current_attributes = parent_attributes; + } + } + + // We don't record module attributes for the root module, + // so we handle that case separately + if module.krate.is_root() { + if module.krate == crate_id { + segments.push(crate_name.to_string()); + } else { + for dep in dependencies { + if dep.crate_id == crate_id { + segments.push(dep.name.to_string()); + break; + } + } + } + }; + + segments.reverse(); + segments.join("::") +} diff --git a/tooling/lsp/src/requests/code_action.rs b/tooling/lsp/src/requests/code_action.rs index 95cdc0b88b4..f5cfabe5141 100644 --- a/tooling/lsp/src/requests/code_action.rs +++ b/tooling/lsp/src/requests/code_action.rs @@ -11,7 +11,7 @@ use lsp_types::{ }; use noirc_errors::Span; use noirc_frontend::{ - ast::{ConstructorExpression, Path, Visitor}, + ast::{ConstructorExpression, NoirTraitImpl, Path, Visitor}, graph::CrateId, hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}, macros_api::NodeInterner, @@ -26,6 +26,7 @@ use crate::{utils, LspState}; use super::{process_request, to_lsp_location}; mod fill_struct_fields; +mod implement_missing_members; mod import_or_qualify; #[cfg(test)] mod tests; @@ -219,4 +220,10 @@ impl<'a> Visitor for CodeActionFinder<'a> { true } + + fn visit_noir_trait_impl(&mut self, noir_trait_impl: &NoirTraitImpl, span: Span) -> bool { + self.implement_missing_members(noir_trait_impl, span); + + true + } } diff --git a/tooling/lsp/src/requests/code_action/implement_missing_members.rs b/tooling/lsp/src/requests/code_action/implement_missing_members.rs new file mode 100644 index 00000000000..eb1a8704131 --- /dev/null +++ b/tooling/lsp/src/requests/code_action/implement_missing_members.rs @@ -0,0 +1,867 @@ +use std::collections::{BTreeMap, HashMap}; + +use lsp_types::TextEdit; +use noirc_errors::{Location, Span}; +use noirc_frontend::{ + ast::{NoirTraitImpl, TraitImplItemKind, UnresolvedTypeData}, + graph::CrateId, + hir::{ + def_map::{CrateDefMap, ModuleId}, + type_check::generics::TraitGenerics, + }, + hir_def::{function::FuncMeta, stmt::HirPattern, traits::Trait}, + macros_api::{ModuleDefId, NodeInterner}, + node_interner::ReferenceId, + Kind, ResolvedGeneric, Type, TypeVariableKind, +}; + +use crate::{byte_span_to_range, modules::relative_module_id_path}; + +use super::CodeActionFinder; + +impl<'a> CodeActionFinder<'a> { + pub(super) fn implement_missing_members( + &mut self, + noir_trait_impl: &NoirTraitImpl, + span: Span, + ) { + if !self.includes_span(span) { + return; + } + + let location = Location::new(noir_trait_impl.trait_name.span(), self.file); + let Some(ReferenceId::Trait(trait_id)) = self.interner.find_referenced(location) else { + return; + }; + + let trait_ = self.interner.get_trait(trait_id); + + // Get all methods + let mut method_ids = trait_.method_ids.clone(); + + // Also get all associated types + let mut associated_types = HashMap::new(); + for associated_type in &trait_.associated_types { + associated_types.insert(associated_type.name.as_ref(), associated_type); + } + + // Remove the ones that already are implemented + for item in &noir_trait_impl.items { + match &item.item.kind { + TraitImplItemKind::Function(noir_function) => { + method_ids.remove(noir_function.name()); + } + TraitImplItemKind::Constant(..) => (), + TraitImplItemKind::Type { name, alias } => { + if let UnresolvedTypeData::Unspecified = alias.typ { + continue; + } + associated_types.remove(&name.0.contents); + } + } + } + + // Also remove default methods + for trait_function in &trait_.methods { + if trait_function.default_impl.is_some() { + method_ids.remove(&trait_function.name.0.contents); + } + } + + if method_ids.is_empty() && associated_types.is_empty() { + return; + } + + let bytes = self.source.as_bytes(); + let right_brace_index = span.end() as usize - 1; + + // Let's find out the indent + let mut cursor = right_brace_index - 1; + while cursor > 0 { + let c = bytes[cursor] as char; + if c == '\n' { + break; + } + if !c.is_whitespace() { + break; + } + cursor -= 1; + } + let cursor_char = bytes[cursor] as char; + + let indent = if cursor_char == '\n' { right_brace_index - cursor - 1 } else { 0 }; + let indent_string = " ".repeat(indent + 4); + + let index = cursor + 1; + + let Some(range) = byte_span_to_range(self.files, self.file, index..index) else { + return; + }; + + let mut method_ids: Vec<_> = method_ids.iter().collect(); + method_ids.sort_by_key(|(name, _)| *name); + + let mut stubs = Vec::new(); + + for (name, _) in associated_types { + stubs.push(format!("{}type {};\n", indent_string, name)); + } + + for (name, func_id) in method_ids { + let func_meta = self.interner.function_meta(func_id); + + let mut generator = MethodStubGenerator::new( + name, + func_meta, + trait_, + noir_trait_impl, + self.interner, + self.def_maps, + self.module_id, + indent + 4, + ); + let stub = generator.generate(); + stubs.push(stub); + } + + let mut new_text = stubs.join("\n"); + if cursor_char != '\n' { + new_text.insert(0, '\n'); + } + + let title = "Implement missing members".to_string(); + let text_edit = TextEdit { range, new_text }; + let code_action = self.new_quick_fix(title, text_edit); + self.code_actions.push(code_action); + } +} + +struct MethodStubGenerator<'a> { + name: &'a str, + func_meta: &'a FuncMeta, + trait_: &'a Trait, + noir_trait_impl: &'a NoirTraitImpl, + interner: &'a NodeInterner, + def_maps: &'a BTreeMap, + module_id: ModuleId, + indent: usize, + string: String, +} + +impl<'a> MethodStubGenerator<'a> { + #[allow(clippy::too_many_arguments)] + fn new( + name: &'a str, + func_meta: &'a FuncMeta, + trait_: &'a Trait, + noir_trait_impl: &'a NoirTraitImpl, + interner: &'a NodeInterner, + def_maps: &'a BTreeMap, + module_id: ModuleId, + indent: usize, + ) -> Self { + Self { + name, + func_meta, + trait_, + noir_trait_impl, + interner, + def_maps, + module_id, + indent, + string: String::new(), + } + } + + fn generate(&mut self) -> String { + let indent_string = " ".repeat(self.indent); + + self.string.push_str(&indent_string); + self.string.push_str("fn "); + self.string.push_str(self.name); + self.append_resolved_generics(&self.func_meta.direct_generics); + self.string.push('('); + for (index, (pattern, typ, _visibility)) in self.func_meta.parameters.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + if self.append_pattern(pattern) { + self.string.push_str(": "); + self.append_type(typ); + } + } + self.string.push(')'); + + let return_type = self.func_meta.return_type(); + if return_type != &Type::Unit { + self.string.push_str(" -> "); + self.append_type(return_type); + } + + if !self.func_meta.trait_constraints.is_empty() { + self.string.push_str(" where "); + for (index, constraint) in self.func_meta.trait_constraints.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(&constraint.typ); + self.string.push_str(": "); + let trait_ = self.interner.get_trait(constraint.trait_id); + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(&constraint.trait_generics); + } + } + + self.string.push_str(" {\n"); + + let body_indent_string = " ".repeat(self.indent + 4); + self.string.push_str(&body_indent_string); + self.string.push_str("panic(f\"Implement "); + self.string.push_str(self.name); + self.string.push_str("\")\n"); + self.string.push_str(&indent_string); + self.string.push_str("}\n"); + std::mem::take(&mut self.string) + } + + /// Appends a pattern and returns true if this was not the self type + fn append_pattern(&mut self, pattern: &HirPattern) -> bool { + match pattern { + HirPattern::Identifier(hir_ident) => { + let definition = self.interner.definition(hir_ident.id); + self.string.push_str(&definition.name); + &definition.name != "self" + } + HirPattern::Mutable(pattern, _) => { + self.string.push_str("mut "); + self.append_pattern(pattern) + } + HirPattern::Tuple(patterns, _) => { + self.string.push('('); + for (index, pattern) in patterns.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_pattern(pattern); + } + self.string.push(')'); + true + } + HirPattern::Struct(typ, patterns, _) => { + self.append_type(typ); + self.string.push_str(" { "); + for (index, (name, _pattern)) in patterns.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.string.push_str(&name.0.contents); + } + self.string.push_str(" }"); + true + } + } + } + + fn append_type(&mut self, typ: &Type) { + match typ { + Type::FieldElement => self.string.push_str("Field"), + Type::Array(n, e) => { + self.string.push('['); + self.append_type(e); + self.string.push_str("; "); + self.append_type(n); + self.string.push(']'); + } + Type::Slice(typ) => { + self.string.push('['); + self.append_type(typ); + self.string.push(']'); + } + Type::Tuple(types) => { + self.string.push('('); + for (index, typ) in types.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(typ); + } + self.string.push(')'); + } + Type::Struct(struct_type, generics) => { + let struct_type = struct_type.borrow(); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the struct type is already imported/visible in this module + let per_ns = current_module_data.find_name(&struct_type.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TypeId(struct_type.id) { + self.string.push_str(&struct_type.name.0.contents); + self.append_generics(generics); + return; + } + } + + let module_id = struct_type.id.module_id(); + let module_data = &self.def_maps[&module_id.krate].modules()[module_id.local_id.0]; + let parent_module_local_id = module_data.parent.unwrap(); + let parent_module_id = + ModuleId { krate: module_id.krate, local_id: parent_module_local_id }; + + let current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&struct_type.name.0.contents); + self.append_generics(generics); + } + Type::Alias(type_alias, generics) => { + let type_alias = type_alias.borrow(); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the alias type is already imported/visible in this module + let per_ns = current_module_data.find_name(&type_alias.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TypeAliasId(type_alias.id) { + self.string.push_str(&type_alias.name.0.contents); + self.append_generics(generics); + return; + } + } + + let parent_module_id = + self.interner.reference_module(ReferenceId::Alias(type_alias.id)).unwrap(); + + let current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + *parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&type_alias.name.0.contents); + self.append_generics(generics); + } + Type::TraitAsType(trait_id, _, trait_generics) => { + let trait_ = self.interner.get_trait(*trait_id); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the trait type is already imported/visible in this module + let per_ns = current_module_data.find_name(&trait_.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TraitId(*trait_id) { + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(trait_generics); + return; + } + } + + let parent_module_id = + self.interner.reference_module(ReferenceId::Trait(*trait_id)).unwrap(); + + let current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + *parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(trait_generics); + } + Type::TypeVariable(typevar, _) => { + if typevar.id() == self.trait_.self_type_typevar.id() { + self.string.push_str("Self"); + return; + } + + let generics = &self.trait_.generics; + if let Some(index) = + generics.iter().position(|generic| generic.type_var.id() == typevar.id()) + { + if let Some(typ) = self.noir_trait_impl.trait_generics.ordered_args.get(index) { + self.string.push_str(&typ.to_string()); + return; + } + } + + for associated_type in &self.trait_.associated_types { + if typevar.id() == associated_type.type_var.id() { + self.string.push_str("Self::"); + self.string.push_str(&associated_type.name); + return; + } + } + + for generic in &self.func_meta.direct_generics { + if typevar.id() == generic.type_var.id() { + self.string.push_str(&generic.name); + return; + } + } + + self.string.push_str("error"); + } + Type::NamedGeneric(typevar, _name, _kind) => { + self.append_type(&Type::TypeVariable(typevar.clone(), TypeVariableKind::Normal)); + } + Type::Function(args, ret, env, unconstrained) => { + if *unconstrained { + self.string.push_str("unconstrained "); + } + self.string.push_str("fn"); + + if let Type::Unit = **env { + } else { + self.string.push('['); + self.append_type(env); + self.string.push(']'); + } + + self.string.push('('); + for (index, arg) in args.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(arg); + } + self.string.push(')'); + + if let Type::Unit = **ret { + } else { + self.string.push_str(" -> "); + self.append_type(ret); + } + } + Type::MutableReference(typ) => { + self.string.push_str("&mut "); + self.append_type(typ); + } + Type::Forall(_, _) => { + panic!("Shouldn't get a Type::Forall"); + } + Type::InfixExpr(left, op, right) => { + self.append_type(left); + self.string.push(' '); + self.string.push_str(&op.to_string()); + self.string.push(' '); + self.append_type(right); + } + Type::Constant(_) + | Type::Integer(_, _) + | Type::Bool + | Type::String(_) + | Type::FmtString(_, _) + | Type::Unit + | Type::Quoted(_) + | Type::Error => self.string.push_str(&typ.to_string()), + } + } + + fn append_generics(&mut self, generics: &[Type]) { + if generics.is_empty() { + return; + } + + self.string.push('<'); + for (index, typ) in generics.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(typ); + } + self.string.push('>'); + } + + fn append_trait_generics(&mut self, generics: &TraitGenerics) { + if generics.named.is_empty() && generics.ordered.is_empty() { + return; + } + + let mut index = 0; + + self.string.push('<'); + for generic in &generics.ordered { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(generic); + index += 1; + } + for named_type in &generics.named { + if index > 0 { + self.string.push_str(", "); + } + self.string.push_str(&named_type.name.0.contents); + self.string.push_str(" = "); + self.append_type(&named_type.typ); + index += 1; + } + self.string.push('>'); + } + + fn append_resolved_generics(&mut self, generics: &[ResolvedGeneric]) { + if generics.is_empty() { + return; + } + + self.string.push('<'); + for (index, generic) in self.func_meta.direct_generics.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_resolved_generic(generic); + } + self.string.push('>'); + } + + fn append_resolved_generic(&mut self, generic: &ResolvedGeneric) { + match &generic.kind { + Kind::Normal => self.string.push_str(&generic.name), + Kind::Numeric(typ) => { + self.string.push_str("let "); + self.string.push_str(&generic.name); + self.string.push_str(": "); + self.append_type(typ); + } + } + } +} + +#[cfg(test)] +mod tests { + use tokio::test; + + use crate::requests::code_action::tests::assert_code_action; + + #[test] + async fn test_add_missing_impl_members_simple() { + let title = "Implement missing members"; + + let src = r#" +trait Trait { + fn foo(x: i32) -> i32; + fn bar() {} +} + +struct Foo {} + +impl Tra>| i32; + fn bar() {} +} + +struct Foo {} + +impl Trait for Foo { + fn foo(x: i32) -> i32 { + panic(f"Implement foo") + } +}"#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_add_missing_impl_members_multiple_with_self_type() { + let title = "Implement missing members"; + + let src = r#" +trait Trait { + fn bar(self) -> Self; + fn foo(x: i32) -> i32; +} + +struct Foo {} + +impl Tra>| Self; + fn foo(x: i32) -> i32; +} + +struct Foo {} + +impl Trait for Foo { + fn bar(self) -> Self { + panic(f"Implement bar") + } + + fn foo(x: i32) -> i32 { + panic(f"Implement foo") + } +}"#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_add_missing_impl_members_qualify_type() { + let title = "Implement missing members"; + + let src = r#" +mod moo { + struct Moo {} + + trait Trait { + fn foo(x: Moo); + } +} + +struct Foo {} + +use moo::Trait; + +impl Tra>|| { + fn foo(x: T) -> [T; N] where M: Bar; +} + +struct Foo {} + +impl Tra>| for Foo { +}"#; + + let expected = r#" +trait Bar {} + +trait Trait { + fn foo(x: T) -> [T; N] where M: Bar; +} + +struct Foo {} + +impl Trait<[U]> for Foo { + fn foo(x: [U]) -> [[U]; N] where M: Bar { + panic(f"Implement foo") + } +}"#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_add_missing_impl_members_associated_types() { + let title = "Implement missing members"; + + let src = r#" +trait Trait { + type Elem; + + fn foo(x: Self::Elem) -> [Self::Elem]; +} + +struct Foo {} + +impl Trait>|< for Foo { +}"#; + + let expected = r#" +trait Trait { + type Elem; + + fn foo(x: Self::Elem) -> [Self::Elem]; +} + +struct Foo {} + +impl Trait for Foo { + type Elem; + + fn foo(x: Self::Elem) -> [Self::Elem] { + panic(f"Implement foo") + } +}"#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_add_missing_impl_members_nested() { + let title = "Implement missing members"; + + let src = r#" +mod moo { + trait Trait { + fn foo(); + fn bar(); + } + + struct Foo {} + + impl Tra>|| CodeActionFinder<'a> { for (module_def_id, visibility, defining_module) in entries { let module_full_path = if let Some(defining_module) = defining_module { - module_id_path( + relative_module_id_path( *defining_module, &self.module_id, current_module_parent_id, self.interner, ) } else { - let Some(module_full_path) = module_full_path( + let Some(module_full_path) = relative_module_full_path( *module_def_id, *visibility, self.module_id, diff --git a/tooling/lsp/src/requests/code_action/tests.rs b/tooling/lsp/src/requests/code_action/tests.rs index a8c81ced2a7..6be2a1ced1a 100644 --- a/tooling/lsp/src/requests/code_action/tests.rs +++ b/tooling/lsp/src/requests/code_action/tests.rs @@ -71,7 +71,10 @@ pub(crate) async fn assert_code_action(title: &str, src: &str, expected: &str) { assert_eq!(text_edits.len(), 1); let result = apply_text_edit(&src.replace(">|<", ""), &text_edits[0]); - assert_eq!(result, expected); + if result != expected { + println!("Expected:\n```\n{}\n```\n\nGot:\n```\n{}\n```", expected, result); + assert_eq!(result, expected); + } } fn apply_text_edit(src: &str, text_edit: &TextEdit) -> String { diff --git a/tooling/lsp/src/requests/completion.rs b/tooling/lsp/src/requests/completion.rs index de5c36bc59f..d07ad826094 100644 --- a/tooling/lsp/src/requests/completion.rs +++ b/tooling/lsp/src/requests/completion.rs @@ -882,7 +882,7 @@ impl<'a> Visitor for NodeFinder<'a> { false } - fn visit_parsed_submodule(&mut self, parsed_sub_module: &ParsedSubModule, span: Span) -> bool { + fn visit_parsed_submodule(&mut self, parsed_sub_module: &ParsedSubModule, _span: Span) -> bool { // Switch `self.module_id` to the submodule let previous_module_id = self.module_id; @@ -897,7 +897,9 @@ impl<'a> Visitor for NodeFinder<'a> { let old_auto_import_line = self.auto_import_line; self.nesting += 1; - if let Some(lsp_location) = to_lsp_location(self.files, self.file, span) { + if let Some(lsp_location) = + to_lsp_location(self.files, self.file, parsed_sub_module.name.span()) + { self.auto_import_line = (lsp_location.range.start.line + 1) as usize; } diff --git a/tooling/lsp/src/requests/completion/auto_import.rs b/tooling/lsp/src/requests/completion/auto_import.rs index d8823794999..f9c5dab0672 100644 --- a/tooling/lsp/src/requests/completion/auto_import.rs +++ b/tooling/lsp/src/requests/completion/auto_import.rs @@ -1,7 +1,7 @@ use lsp_types::{Position, Range, TextEdit}; use noirc_frontend::macros_api::ModuleDefId; -use crate::modules::{get_parent_module_id, module_full_path, module_id_path}; +use crate::modules::{get_parent_module_id, relative_module_full_path, relative_module_id_path}; use super::{ kinds::{FunctionCompletionKind, FunctionKind, RequestedItems}, @@ -40,14 +40,14 @@ impl<'a> NodeFinder<'a> { }; let module_full_path = if let Some(defining_module) = defining_module { - module_id_path( + relative_module_id_path( *defining_module, &self.module_id, current_module_parent_id, self.interner, ) } else { - let Some(module_full_path) = module_full_path( + let Some(module_full_path) = relative_module_full_path( *module_def_id, *visibility, self.module_id, diff --git a/tooling/lsp/src/requests/completion/tests.rs b/tooling/lsp/src/requests/completion/tests.rs index 7e11e0d9d52..6809e24e645 100644 --- a/tooling/lsp/src/requests/completion/tests.rs +++ b/tooling/lsp/src/requests/completion/tests.rs @@ -1395,6 +1395,7 @@ mod completion_tests { #[test] async fn test_auto_imports_when_in_nested_module_and_item_is_further_nested() { let src = r#" + #[something] mod foo { mod bar { pub fn hello_world() {} @@ -1422,8 +1423,8 @@ mod completion_tests { item.additional_text_edits, Some(vec![TextEdit { range: Range { - start: Position { line: 2, character: 4 }, - end: Position { line: 2, character: 4 }, + start: Position { line: 3, character: 4 }, + end: Position { line: 3, character: 4 }, }, new_text: "use bar::hello_world;\n\n ".to_string(), }]) diff --git a/tooling/lsp/src/requests/document_symbol.rs b/tooling/lsp/src/requests/document_symbol.rs index 7ab0a45ad0a..6c41f4dc2e5 100644 --- a/tooling/lsp/src/requests/document_symbol.rs +++ b/tooling/lsp/src/requests/document_symbol.rs @@ -378,12 +378,18 @@ impl<'a> Visitor for DocumentSymbolCollector<'a> { name: &Ident, typ: &UnresolvedType, default_value: &Expression, + _span: Span, ) -> bool { self.collect_in_constant(name, typ, Some(default_value)); false } - fn visit_trait_impl_item_type(&mut self, name: &Ident, alias: &UnresolvedType) -> bool { + fn visit_trait_impl_item_type( + &mut self, + name: &Ident, + alias: &UnresolvedType, + _span: Span, + ) -> bool { self.collect_in_type(name, Some(alias)); false } @@ -662,7 +668,7 @@ mod document_symbol_tests { tags: None, deprecated: None, range: Range { - start: Position { line: 19, character: 7 }, + start: Position { line: 19, character: 4 }, end: Position { line: 20, character: 5 }, }, selection_range: Range { diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index dab6ddd0fc6..8e9666a624b 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -14,7 +14,7 @@ use noirc_frontend::{ Generics, Shared, StructType, Type, TypeAlias, TypeBinding, TypeVariable, }; -use crate::LspState; +use crate::{modules::module_full_path, LspState}; use super::{process_request, to_lsp_location, ProcessRequestCallbackArgs}; @@ -352,43 +352,14 @@ fn format_parent_module_from_module_id( args: &ProcessRequestCallbackArgs, string: &mut String, ) -> bool { - let mut segments: Vec<&str> = Vec::new(); - - if let Some(module_attributes) = args.interner.try_module_attributes(module) { - segments.push(&module_attributes.name); - - let mut current_attributes = module_attributes; - loop { - let Some(parent_local_id) = current_attributes.parent else { - break; - }; - - let Some(parent_attributes) = args.interner.try_module_attributes(&ModuleId { - krate: module.krate, - local_id: parent_local_id, - }) else { - break; - }; - - segments.push(&parent_attributes.name); - current_attributes = parent_attributes; - } - } - - // We don't record module attributes for the root module, - // so we handle that case separately - if module.krate.is_root() { - segments.push(&args.crate_name); - }; - - if segments.is_empty() { + let full_path = + module_full_path(module, args.interner, args.crate_id, &args.crate_name, args.dependencies); + if full_path.is_empty() { return false; } - segments.reverse(); - string.push_str(" "); - string.push_str(&segments.join("::")); + string.push_str(&full_path); true } diff --git a/tooling/nargo/src/errors.rs b/tooling/nargo/src/errors.rs index 0b8378702cb..4a72bb1ec78 100644 --- a/tooling/nargo/src/errors.rs +++ b/tooling/nargo/src/errors.rs @@ -115,6 +115,10 @@ fn extract_locations_from_error( OpcodeResolutionError::IndexOutOfBounds { opcode_location: error_location, .. }, acir_call_stack, ) + | ExecutionError::SolvingError( + OpcodeResolutionError::InvalidInputBitSize { opcode_location: error_location, .. }, + acir_call_stack, + ) | ExecutionError::SolvingError( OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: error_location, .. }, acir_call_stack, diff --git a/tooling/nargo/src/ops/execute.rs b/tooling/nargo/src/ops/execute.rs index 59d554d7ca5..eb03bdf01c1 100644 --- a/tooling/nargo/src/ops/execute.rs +++ b/tooling/nargo/src/ops/execute.rs @@ -89,6 +89,10 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> | OpcodeResolutionError::IndexOutOfBounds { opcode_location: ErrorLocation::Resolved(opcode_location), .. + } + | OpcodeResolutionError::InvalidInputBitSize { + opcode_location: ErrorLocation::Resolved(opcode_location), + .. } => { let resolved_location = ResolvedOpcodeLocation { acir_function_index: self.current_function_index, diff --git a/tooling/nargo/src/ops/test.rs b/tooling/nargo/src/ops/test.rs index efe648e09b0..370a4235f61 100644 --- a/tooling/nargo/src/ops/test.rs +++ b/tooling/nargo/src/ops/test.rs @@ -191,8 +191,16 @@ fn check_expected_failure_message( None => return TestStatus::Pass, }; - let expected_failure_message_matches = - matches!(&failed_assertion, Some(message) if message.contains(expected_failure_message)); + // Match the failure message that the user will see, i.e. the failed_assertion + // if present or else the error_diagnostic's message, against the + // expected_failure_message + let expected_failure_message_matches = failed_assertion + .as_ref() + .or_else(|| { + error_diagnostic.as_ref().map(|file_diagnostic| &file_diagnostic.diagnostic.message) + }) + .map(|message| message.contains(expected_failure_message)) + .unwrap_or(false); if expected_failure_message_matches { return TestStatus::Pass; } diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index ba9a8214702..7d5e1886072 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -7,7 +7,7 @@ use crate::{ visitor::expr::{format_seq, NewlineMode}, }; use noirc_frontend::{ - ast::{NoirFunction, Visibility}, + ast::{NoirFunction, TraitImplItemKind, Visibility}, macros_api::UnresolvedTypeData, }; use noirc_frontend::{ @@ -226,6 +226,47 @@ impl super::FmtVisitor<'_> { self.last_position = span.end(); } } + ItemKind::TraitImpl(noir_trait_impl) => { + self.format_missing_indent(span.start(), true); + + if std::mem::take(&mut self.ignore_next_node) { + self.push_str(self.slice(span)); + self.last_position = span.end(); + continue; + } + + let before_brace = self.span_before(span, Token::LeftBrace).start(); + let slice = self.slice(self.last_position..before_brace).trim(); + let after_brace = self.span_after(span, Token::LeftBrace).start(); + self.last_position = after_brace; + + self.push_str(&format!("{slice} ")); + + if noir_trait_impl.items.is_empty() { + self.visit_empty_block((after_brace - 1..span.end()).into()); + continue; + } else { + self.push_str("{"); + self.indent.block_indent(self.config); + + for documented_item in noir_trait_impl.items { + let span = documented_item.item.span; + match documented_item.item.kind { + TraitImplItemKind::Function(method) => { + self.visit_function(span, method); + } + TraitImplItemKind::Constant(..) + | TraitImplItemKind::Type { .. } => { + self.push_rewrite(self.slice(span).to_string(), span); + self.last_position = span.end(); + } + } + } + + self.close_block((self.last_position..span.end() - 1).into()); + self.last_position = span.end(); + } + } ItemKind::Import(use_tree, visibility) => { let use_tree = UseTree::from_ast(use_tree); let use_tree = use_tree.rewrite_top_level(self, self.shape(), visibility); @@ -234,7 +275,6 @@ impl super::FmtVisitor<'_> { } ItemKind::Struct(_) | ItemKind::Trait(_) - | ItemKind::TraitImpl(_) | ItemKind::TypeAlias(_) | ItemKind::Global(_) | ItemKind::ModuleDecl(_) diff --git a/tooling/nargo_fmt/tests/input/impl.nr b/tooling/nargo_fmt/tests/input/impl.nr index 21ce6a2e175..e4adb8ebd6a 100644 --- a/tooling/nargo_fmt/tests/input/impl.nr +++ b/tooling/nargo_fmt/tests/input/impl.nr @@ -21,7 +21,7 @@ impl MyType { } impl MyStruct where T: MyEq { - fn my_eq(self, other: Self) -> bool { +fn my_eq(self, other: Self) -> bool { (self.a == other.a) & self.b.my_eq(other.b) } } diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index 4ec715e27eb..0d71e471b38 100644 --- a/tooling/noir_js_backend_barretenberg/package.json +++ b/tooling/noir_js_backend_barretenberg/package.json @@ -41,7 +41,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.51.1", + "@aztec/bb.js": "0.55.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/tooling/profiler/src/opcode_formatter.rs b/tooling/profiler/src/opcode_formatter.rs index 56c00bb856b..fa72793e406 100644 --- a/tooling/profiler/src/opcode_formatter.rs +++ b/tooling/profiler/src/opcode_formatter.rs @@ -123,6 +123,7 @@ fn format_brillig_opcode_kind(opcode: &BrilligOpcode) -> String { BrilligOpcode::BinaryIntOp { op, bit_size, .. } => { format!("{bit_size}::{}", format_binary_int(op)) } + BrilligOpcode::Not { .. } => "not".to_string(), BrilligOpcode::BlackBox(func) => format!("blackbox::{}", format_blackbox_op(func)), BrilligOpcode::Call { .. } => "call".to_string(), BrilligOpcode::CalldataCopy { .. } => "calldata_copy".to_string(), diff --git a/yarn.lock b/yarn.lock index 5d1d41f58fd..5d713532c67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -221,9 +221,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.51.1": - version: 0.51.1 - resolution: "@aztec/bb.js@npm:0.51.1" +"@aztec/bb.js@npm:0.55.0": + version: 0.55.0 + resolution: "@aztec/bb.js@npm:0.55.0" dependencies: comlink: ^4.4.1 commander: ^10.0.1 @@ -231,7 +231,7 @@ __metadata: tslib: ^2.4.0 bin: bb.js: dest/node/main.js - checksum: 246953d4d2becc86001b8e6d49ab8c0b4fa4833a9bf1d2177d0fb4e271e66f9dc65e3b02b69b00fbfcb935a11e2f90b5ac229b8c8938c34604fe54b29b3accfb + checksum: 18ae18a962e05fd28e15e17796ec08e889ea331ec1790f8c77aa1d9472b4942c8f03c2cb8d8366a2e7a6896ffc135cdfc5b3bb6c9743bdf85e183f771c4f7b88 languageName: node linkType: hard @@ -4161,7 +4161,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.51.1 + "@aztec/bb.js": 0.55.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3