diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/6_array/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/6_array/src/main.nr index b9ed6b6f345..3b98a2b99bb 100644 --- a/crates/nargo_cli/tests/test_data_ssa_refactor/6_array/src/main.nr +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/6_array/src/main.nr @@ -50,4 +50,9 @@ fn main(x: [u32; 5], y: [u32; 5], mut z: u32, t: u32) { assert(x_elem != y_elem); } } + + // Test 7: Arrays of tuples/structs + let mut tuple_array = [(1, 2), (3, 4), (5, 6)]; + tuple_array[1] = (7, 8); + assert(tuple_array[1].1 == 8); } diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs index fca871ae895..346b0b92df2 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs @@ -64,7 +64,7 @@ impl Value { Value::Instruction { typ, .. } => typ.clone(), Value::Param { typ, .. } => typ.clone(), Value::NumericConstant { typ, .. } => typ.clone(), - Value::Array { element_type, array } => Type::Array(element_type.clone(), array.len()), + Value::Array { element_type, array } => Type::Array(element_type.clone(), array.len() / element_type.len()), Value::Function { .. } => Type::Function, Value::Intrinsic { .. } => Type::Function, Value::ForeignFunction { .. } => Type::Function, diff --git a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs index 07ee32998d2..769ee6aa09f 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs @@ -558,10 +558,20 @@ impl<'a> FunctionContext<'a> { pub(super) fn assign_new_value(&mut self, lvalue: LValue, new_value: Values) { match lvalue { LValue::Ident(references) => self.assign(references, new_value), - LValue::Index { old_array, index, array_lvalue } => { - let rvalue = new_value.into_leaf().eval(self); // TODO - let new_array = self.builder.insert_array_set(old_array, index, rvalue); - self.assign_new_value(*array_lvalue, new_array.into()); + LValue::Index { old_array: mut array, index, array_lvalue } => { + let element_size = self.builder.field_constant(self.element_size(array)); + + // The actual base index is the user's index * the array element type's size + let mut index = self.builder.insert_binary(index, BinaryOp::Mul, element_size); + let one = self.builder.field_constant(FieldElement::one()); + + new_value.for_each(|value| { + let value = value.eval(self); + array = self.builder.insert_array_set(array, index, value); + index = self.builder.insert_binary(index, BinaryOp::Add, one); + }); + + self.assign_new_value(*array_lvalue, array.into()); } LValue::MemberAccess { old_object, index, object_lvalue } => { let new_object = Self::replace_field(old_object, index, new_value); @@ -573,6 +583,13 @@ impl<'a> FunctionContext<'a> { } } + fn element_size(&self, array: ValueId) -> FieldElement { + match self.builder.type_of_value(array) { + Type::Array(elements, _) | Type::Slice(elements) => (elements.len() as u128).into(), + t => panic!("Uncaught type error: tried to take element size of non-array type {t}"), + } + } + /// Given an lhs containing only references, create a store instruction to store each value of /// rhs into its corresponding value in lhs. fn assign(&mut self, lhs: Values, rhs: Values) {