diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs index 9d400a7d619..df8afc29d99 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs @@ -122,6 +122,14 @@ impl AcirContext { self.add_data(var_data) } + /// True if the given AcirVar refers to a constant one value + pub(crate) fn is_constant_one(&self, var: &AcirVar) -> bool { + match self.vars[var] { + AcirVarData::Const(field) => field.is_one(), + _ => false, + } + } + /// Adds a new Variable to context whose value will /// be constrained to be the negation of `var`. /// diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs index ace4d054a2a..a7e4e8489bc 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs @@ -105,10 +105,18 @@ impl Context { } fn convert_ssa_block_param(&mut self, param_type: &Type) -> AcirValue { + self.create_value_from_type(param_type, |this, typ| this.add_numeric_input_var(&typ)) + } + + fn create_value_from_type( + &mut self, + param_type: &Type, + mut make_var: impl FnMut(&mut Self, NumericType) -> AcirVar, + ) -> AcirValue { match param_type { Type::Numeric(numeric_type) => { let typ = AcirType::new(*numeric_type); - AcirValue::Var(self.add_numeric_input_var(numeric_type), typ) + AcirValue::Var(make_var(self, *numeric_type), typ) } Type::Array(element_types, length) => { let mut elements = im::Vector::new(); @@ -284,6 +292,20 @@ impl Context { .try_to_u64() .expect("Expected array index to fit into a u64") as usize; + if index >= array.len() { + // Ignore the error if side effects are disabled. + if let Some(var) = self.current_side_effects_enabled_var { + if self.acir_context.is_constant_one(&var) { + // TODO: Can we save a source Location for this error? + panic!("Index {} is out of bounds for array of length {}", index, array.len()); + } + } + let result_type = dfg.type_of_value(dfg.instruction_results(instruction)[0]); + let value = self.create_default_value(&result_type); + self.define_result(dfg, instruction, value); + return; + } + let value = match store_value { Some(store_value) => { let store_value = self.convert_value(store_value, dfg); @@ -680,6 +702,13 @@ impl Context { } } } + + /// Creates a default, meaningless value meant only to be a valid value of the given type. + fn create_default_value(&mut self, param_type: &Type) -> AcirValue { + self.create_value_from_type(param_type, |this, _| { + this.acir_context.add_constant(FieldElement::zero()) + }) + } } #[cfg(test)]