Skip to content

Commit

Permalink
fix(ssa): Use accurate type during SSA AsSlice simplficiation (#4610)
Browse files Browse the repository at this point in the history
# Description

## Problem\*

Resolves #4609 

## Summary\*

We were not accurately converting the type from an array to a slice
during `AsSlice` SSA simplification. This led to the slice capacity
tracker not accurately tracking the slice size.

## Additional Context


## Documentation\*

Check one:
- [ ] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [ ] I have tested the changes locally.
- [ ] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
vezenovm committed Mar 21, 2024
1 parent 13eb71b commit 0473497
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 4 deletions.
9 changes: 5 additions & 4 deletions compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,11 @@ pub(super) fn simplify_call(
}
}
Intrinsic::AsSlice => {
let slice = dfg.get_array_constant(arguments[0]);
if let Some((slice, element_type)) = slice {
let slice_length = dfg.make_constant(slice.len().into(), Type::length_type());
let new_slice = dfg.make_array(slice, element_type);
let array = dfg.get_array_constant(arguments[0]);
if let Some((array, array_type)) = array {
let slice_length = dfg.make_constant(array.len().into(), Type::length_type());
let inner_element_types = array_type.element_types();
let new_slice = dfg.make_array(array, Type::Slice(inner_element_types));
SimplifyResult::SimplifiedToMultiple(vec![slice_length, new_slice])
} else {
SimplifyResult::None
Expand Down
7 changes: 7 additions & 0 deletions compiler/noirc_evaluator/src/ssa/ir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ impl Type {
Type::Reference(element) => element.contains_an_array(),
}
}

pub(crate) fn element_types(self) -> Rc<Vec<Type>> {
match self {
Type::Array(element_types, _) | Type::Slice(element_types) => element_types,
other => panic!("element_types: Expected array or slice, found {other}"),
}
}
}

/// Composite Types are essentially flattened struct or tuple types.
Expand Down
23 changes: 23 additions & 0 deletions test_programs/execution_success/array_to_slice/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ fn as_slice_push<T, N>(xs: [T; N]) -> [T] {
slice
}

// Expected that x == 0 and y == 1
fn main(x: Field, y: pub Field) {
let xs: [Field; 0] = [];
let ys: [Field; 1] = [1];
Expand All @@ -30,4 +31,26 @@ fn main(x: Field, y: pub Field) {
assert(dynamic.as_slice()[2] == dynamic_expected[2]);
assert(dynamic.as_slice()[3] == dynamic_expected[3]);
assert(dynamic.as_slice().len() == 4);

regression_4609_append_slices(x, y);
regression_4609_append_dynamic_slices(x, y);
}

fn regression_4609_append_slices(x: Field, y: Field) {
let sl = [x, 1, 2, 3].as_slice();
let sl2 = [y, 5, 6].as_slice();
let sl3 = sl.append(sl2);
assert(sl3[0] == x);
assert(sl3[4] == y);
}

fn regression_4609_append_dynamic_slices(x: Field, y: Field) {
let mut sl = [x, 1, 2, 3].as_slice();
sl[x] = x + 10;
let mut sl2 = [y, 5, 6].as_slice();
sl2[y] = y + 5;
let sl3 = sl.append(sl2);
assert(sl3[0] == 10);
assert(sl3[4] == y);
assert(sl3[5] == 6);
}

0 comments on commit 0473497

Please sign in to comment.