From 8270cac39d23f65ca5e2462746a0760662c4af7a Mon Sep 17 00:00:00 2001 From: jfecher Date: Tue, 10 Oct 2023 12:33:54 -0500 Subject: [PATCH] feat: Implement automatic dereferencing for index expressions (#3082) --- .../noirc_frontend/src/hir/type_check/expr.rs | 16 +++++++++++++--- .../compile_success_empty/auto_deref/Nargo.toml | 7 +++++++ .../compile_success_empty/auto_deref/src/main.nr | 5 +++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml create mode 100644 tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 76a0cca4758..3b61f2b2b6b 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -128,7 +128,7 @@ impl<'interner> TypeChecker<'interner> { Type::Error }) } - HirExpression::Index(index_expr) => self.check_index_expression(index_expr), + HirExpression::Index(index_expr) => self.check_index_expression(expr_id, index_expr), HirExpression::Call(call_expr) => { self.check_if_deprecated(&call_expr.func); @@ -396,7 +396,11 @@ impl<'interner> TypeChecker<'interner> { } } - fn check_index_expression(&mut self, index_expr: expr::HirIndexExpression) -> Type { + fn check_index_expression( + &mut self, + id: &ExprId, + mut index_expr: expr::HirIndexExpression, + ) -> Type { let index_type = self.check_expression(&index_expr.index); let span = self.interner.expr_span(&index_expr.index); @@ -408,14 +412,20 @@ impl<'interner> TypeChecker<'interner> { } }); + // When writing `a[i]`, if `a : &mut ...` then automatically dereference `a` as many + // times as needed to get the underlying array. let lhs_type = self.check_expression(&index_expr.collection); + let (new_lhs, lhs_type) = self.insert_auto_dereferences(index_expr.collection, lhs_type); + index_expr.collection = new_lhs; + self.interner.replace_expr(id, HirExpression::Index(index_expr)); + match lhs_type.follow_bindings() { // XXX: We can check the array bounds here also, but it may be better to constant fold first // and have ConstId instead of ExprId for constants Type::Array(_, base_type) => *base_type, Type::Error => Type::Error, typ => { - let span = self.interner.expr_span(&index_expr.collection); + let span = self.interner.expr_span(&new_lhs); self.errors.push(TypeCheckError::TypeMismatch { expected_typ: "Array".to_owned(), expr_typ: typ.to_string(), diff --git a/tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml new file mode 100644 index 00000000000..cc1c9a8d8f7 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "auto_deref" +type = "bin" +authors = [""] +compiler_version = "0.16.0" + +[dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr new file mode 100644 index 00000000000..1225885d765 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr @@ -0,0 +1,5 @@ + +fn main() { + let a = &mut [1, 2, 3]; + assert(a[0] == 1); +}