Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/elaborator/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ impl Elaborator<'_> {
self.local_module = Some(func_meta.source_module);
self.self_type = func_meta.self_type.clone();
self.current_trait_impl = func_meta.trait_impl;
self.reset_lvalue_index_counter();

self.scopes.start_function();
let old_item = self.current_item.replace(DependencyId::Function(id));
Expand Down
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/elaborator/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ impl Elaborator<'_> {
self.push_err(ResolverError::MutableGlobal { location });
}

self.reset_lvalue_index_counter();
let (let_statement, _typ) = self.elaborate_let(let_stmt, Some(global_id));

// References cannot be stored in globals because they would outlive their referents.
Expand Down
27 changes: 27 additions & 0 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,22 @@ pub struct Elaborator<'context> {
/// when an attribute generates code that triggers further attribute expansion.
/// This is a global counter that catches both single-function and mutual recursion.
pub(crate) macro_expansion_depth: usize,

/// Counter used to define temporary variables for non-simple indexes in l-values.
///
/// For example, this expression:
///
/// ```noir
/// array[x + y] = 10;
/// ```
///
/// is transformed into:
///
/// ```noir
/// let i_0 = x + y;
/// array[i_0] = 10;
/// ```
lvalue_index_counter: usize,
}

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -363,6 +379,7 @@ impl<'context> Elaborator<'context> {
elaborate_reasons,
comptime_evaluation_halted: false,
macro_expansion_depth: 0,
lvalue_index_counter: 0,
}
}

Expand Down Expand Up @@ -838,6 +855,16 @@ impl<'context> Elaborator<'context> {
pub(crate) fn interpreter_call_stack(&self) -> &im::Vector<Location> {
&self.interpreter_call_stack
}

pub(crate) fn reset_lvalue_index_counter(&mut self) {
self.lvalue_index_counter = 0;
}

pub(crate) fn next_lvalue_index_counter(&mut self) -> usize {
let lvalue_index_counter = self.lvalue_index_counter;
self.lvalue_index_counter += 1;
lvalue_index_counter
}
}

#[cfg(feature = "test_utils")]
Expand Down
3 changes: 2 additions & 1 deletion compiler/noirc_frontend/src/elaborator/statements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,8 +719,9 @@ impl Elaborator<'_> {
return None;
}

let lvalue_index_counter = self.next_lvalue_index_counter();
let id = self.interner.push_definition(
format!("i_{}", self.interner.definition_count()),
format!("i_{lvalue_index_counter}"),
false,
false,
DefinitionKind::Local(None),
Expand Down
38 changes: 19 additions & 19 deletions compiler/noirc_frontend/src/tests/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ fn mutate_in_lvalue_block_expr() {
mutate_in_lvalue();
();
}

fn mutate_in_lvalue() {
let mut a: ([Field; 2], Field) = ([1_Field, 2_Field], 3_Field);
{
let i_3: u32 = {
let i_0: u32 = {
a = ([4_Field, 5_Field], 6_Field);
1_u32
};
a.0[i_3] = 7_Field;
a.0[i_0] = 7_Field;
};
assert(a.0[0_u32] == 4_Field);
assert(a.0[1_u32] == 7_Field);
Expand Down Expand Up @@ -81,15 +81,15 @@ fn multiple_block_expressions_in_lvalue() {
fn main() {
let mut arr: [[Field; 2]; 2] = [[1_Field, 2_Field], [3_Field, 4_Field]];
{
let i_2: u32 = {
let i_0: u32 = {
arr = [[5_Field, 6_Field], [7_Field, 8_Field]];
0_u32
};
let i_3: u32 = {
let i_1: u32 = {
arr[0_u32][0_u32] = 9_Field;
1_u32
};
arr[i_2][i_3] = 10_Field;
arr[i_0][i_1] = 10_Field;
};
assert(arr[0_u32][0_u32] == 9_Field);
assert(arr[0_u32][1_u32] == 10_Field);
Expand Down Expand Up @@ -134,19 +134,19 @@ fn deeply_nested_block_expressions_in_lvalue() {
fn main() {
let mut arr: [[Field; 2]; 2] = [[1_Field, 2_Field], [3_Field, 4_Field]];
{
let i_3: u32 = {
let i_0: u32 = {
let x: u32 = {
arr = [[10_Field, 20_Field], [30_Field, 40_Field]];
0_u32
};
arr = [[100_Field, 200_Field], [300_Field, 400_Field]];
x
};
let i_4: u32 = {
let i_1: u32 = {
arr = [[1000_Field, 2000_Field], [3000_Field, 4000_Field]];
1_u32
};
arr[i_3][i_4] = 5000_Field;
arr[i_0][i_1] = 5000_Field;
};
assert(arr[0_u32][0_u32] == 1000_Field);
assert(arr[0_u32][1_u32] == 5000_Field);
Expand Down Expand Up @@ -184,15 +184,15 @@ fn nested_array_index_side_effect_ordering() {
*c = *c + 1_Field;
old as u32
}

fn main() {
let mut counter: Field = 0_Field;
let mut arr: [[[Field; 2]; 2]; 2] = [[[0_Field; 2]; 2]; 2];
{
let i_6: u32 = inc(&mut counter);
let i_7: u32 = inc(&mut counter);
let i_8: u32 = inc(&mut counter);
arr[i_6][i_7][i_8] = 42_Field;
let i_0: u32 = inc(&mut counter);
let i_1: u32 = inc(&mut counter);
let i_2: u32 = inc(&mut counter);
arr[i_0][i_1][i_2] = 42_Field;
};
assert(counter == 3_Field);
assert(arr[0_u32][1_u32][2_u32] == 42_Field);
Expand Down Expand Up @@ -230,20 +230,20 @@ fn member_access_then_array_index_ordering() {
struct Foo {
arrays: [[Field; 2]; 2],
}

fn inc(c: &mut Field) -> u32 {
let old: Field = *c;
*c = *c + 1_Field;
old as u32
}

fn main() {
let mut counter: Field = 0_Field;
let mut foo: Foo = Foo { arrays: [[0_Field; 2]; 2]};
{
let i_6: u32 = inc(&mut counter);
let i_7: u32 = inc(&mut counter);
foo.arrays[i_6][i_7] = 55_Field;
let i_0: u32 = inc(&mut counter);
let i_1: u32 = inc(&mut counter);
foo.arrays[i_0][i_1] = 55_Field;
};
assert(counter == 2_Field);
assert(foo.arrays[0_u32][1_u32] == 55_Field);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading