@@ -424,7 +424,9 @@ impl Context {
424424 let rhs_var = read_from_index ( rhs_block_id, i) ?;
425425 Ok ( ( lhs_var, rhs_var) )
426426 } ) ,
427- _ => unreachable ! ( "ICE: lhs and rhs should be of the same type" ) ,
427+ _ => {
428+ unreachable ! ( "ICE: lhs and rhs should be of the same type" )
429+ }
428430 }
429431 }
430432
@@ -502,7 +504,7 @@ impl Context {
502504 self . initialize_array ( block_id, len, Some ( output. clone ( ) ) ) ?;
503505 }
504506 AcirValue :: DynamicArray ( _) => {
505- unreachable ! ( "The output from an intrinsic call is expected to be a single value or an array but got {output:?}" ) ;
507+ // Do nothing as a dynamic array returned from a slice intrinsic should already be initialized
506508 }
507509 AcirValue :: Var ( _, _) => {
508510 // Do nothing
@@ -1018,7 +1020,8 @@ impl Context {
10181020 }
10191021 }
10201022
1021- let element_type_sizes = self . init_element_type_sizes_array ( & array_typ, array_id, dfg) ?;
1023+ let element_type_sizes =
1024+ self . init_element_type_sizes_array ( & array_typ, array_id, None , dfg) ?;
10221025 let result_value = AcirValue :: DynamicArray ( AcirDynamicArray {
10231026 block_id : result_block_id,
10241027 len : array_len,
@@ -1105,6 +1108,7 @@ impl Context {
11051108 & mut self ,
11061109 array_typ : & Type ,
11071110 array_id : ValueId ,
1111+ array_acir_value : Option < AcirValue > ,
11081112 dfg : & DataFlowGraph ,
11091113 ) -> Result < BlockId , RuntimeError > {
11101114 let element_type_sizes = self . internal_block_id ( & array_id) ;
@@ -1132,7 +1136,11 @@ impl Context {
11321136 Value :: Instruction { .. } | Value :: Param { .. } => {
11331137 // An instruction representing the slice means it has been processed previously during ACIR gen.
11341138 // Use the previously defined result of an array operation to fetch the internal type information.
1135- let array_acir_value = self . convert_value ( array_id, dfg) ;
1139+ let array_acir_value = if let Some ( array_acir_value) = array_acir_value {
1140+ array_acir_value
1141+ } else {
1142+ self . convert_value ( array_id, dfg)
1143+ } ;
11361144 match array_acir_value {
11371145 AcirValue :: DynamicArray ( AcirDynamicArray {
11381146 element_type_sizes : inner_elem_type_sizes,
@@ -1274,7 +1282,8 @@ impl Context {
12741282 var_index : AcirVar ,
12751283 dfg : & DataFlowGraph ,
12761284 ) -> Result < AcirVar , RuntimeError > {
1277- let element_type_sizes = self . init_element_type_sizes_array ( array_typ, array_id, dfg) ?;
1285+ let element_type_sizes =
1286+ self . init_element_type_sizes_array ( array_typ, array_id, None , dfg) ?;
12781287
12791288 let predicate_index =
12801289 self . acir_context . mul_var ( var_index, self . current_side_effects_enabled_var ) ?;
@@ -1728,26 +1737,50 @@ impl Context {
17281737 }
17291738 Intrinsic :: SlicePushBack => {
17301739 let slice_length = self . convert_value ( arguments[ 0 ] , dfg) . into_var ( ) ?;
1740+ let ( array_id, array_typ, _) =
1741+ self . check_array_is_initialized ( arguments[ 1 ] , dfg) ?;
17311742 let slice = self . convert_value ( arguments[ 1 ] , dfg) ;
1732- // TODO(#2461): make sure that we have handled nested struct inputs
1733- let element = self . convert_value ( arguments[ 2 ] , dfg) ;
17341743
1744+ // TODO(#3364): make sure that we have handled nested struct inputs
1745+ let element = self . convert_value ( arguments[ 2 ] , dfg) ;
17351746 let one = self . acir_context . add_constant ( FieldElement :: one ( ) ) ;
17361747 let new_slice_length = self . acir_context . add_var ( slice_length, one) ?;
17371748
1749+ // We attach the element no matter what in case len == capacity, as otherwise we
1750+ // may get an out of bounds error.
17381751 let mut new_slice = Vector :: new ( ) ;
1739- self . slice_intrinsic_input ( & mut new_slice, slice) ?;
1740- new_slice. push_back ( element) ;
1741-
1742- Ok ( vec ! [
1743- AcirValue :: Var ( new_slice_length, AcirType :: field( ) ) ,
1744- AcirValue :: Array ( new_slice) ,
1745- ] )
1752+ self . slice_intrinsic_input ( & mut new_slice, slice. clone ( ) ) ?;
1753+ new_slice. push_back ( element. clone ( ) ) ;
1754+
1755+ // TODO(#3364): This works for non-nested outputs
1756+ let len = Self :: flattened_value_size ( & slice) ;
1757+ let new_elem_size = Self :: flattened_value_size ( & element) ;
1758+ let new_slice_val = AcirValue :: Array ( new_slice) ;
1759+ let result_block_id = self . block_id ( & result_ids[ 1 ] ) ;
1760+ self . initialize_array (
1761+ result_block_id,
1762+ len + new_elem_size,
1763+ Some ( new_slice_val. clone ( ) ) ,
1764+ ) ?;
1765+ let mut var_index = slice_length;
1766+ self . array_set_value ( element, result_block_id, & mut var_index) ?;
1767+
1768+ let result = AcirValue :: DynamicArray ( AcirDynamicArray {
1769+ block_id : result_block_id,
1770+ len : len + new_elem_size,
1771+ element_type_sizes : self . init_element_type_sizes_array (
1772+ & array_typ,
1773+ array_id,
1774+ Some ( new_slice_val) ,
1775+ dfg,
1776+ ) ?,
1777+ } ) ;
1778+ Ok ( vec ! [ AcirValue :: Var ( new_slice_length, AcirType :: field( ) ) , result] )
17461779 }
17471780 Intrinsic :: SlicePushFront => {
17481781 let slice_length = self . convert_value ( arguments[ 0 ] , dfg) . into_var ( ) ?;
1749- let slice = self . convert_value ( arguments[ 1 ] , dfg) ;
1750- // TODO(#2461 ): make sure that we have handled nested struct inputs
1782+ let slice: AcirValue = self . convert_value ( arguments[ 1 ] , dfg) ;
1783+ // TODO(#3364 ): make sure that we have handled nested struct inputs
17511784 let element = self . convert_value ( arguments[ 2 ] , dfg) ;
17521785
17531786 let one = self . acir_context . add_constant ( FieldElement :: one ( ) ) ;
@@ -1769,12 +1802,18 @@ impl Context {
17691802 let one = self . acir_context . add_constant ( FieldElement :: one ( ) ) ;
17701803 let new_slice_length = self . acir_context . sub_var ( slice_length, one) ?;
17711804
1805+ let ( _, _, block_id) = self . check_array_is_initialized ( arguments[ 1 ] , dfg) ?;
1806+ let mut var_index = new_slice_length;
1807+ let elem = self . array_get_value (
1808+ & dfg. type_of_value ( result_ids[ 2 ] ) ,
1809+ block_id,
1810+ & mut var_index,
1811+ & [ ] ,
1812+ ) ?;
1813+
1814+ // TODO(#3364): make sure that we have handled nested struct inputs
17721815 let mut new_slice = Vector :: new ( ) ;
17731816 self . slice_intrinsic_input ( & mut new_slice, slice) ?;
1774- // TODO(#2461): make sure that we have handled nested struct inputs
1775- let elem = new_slice
1776- . pop_back ( )
1777- . expect ( "There are no elements in this slice to be removed" ) ;
17781817
17791818 Ok ( vec ! [
17801819 AcirValue :: Var ( new_slice_length, AcirType :: field( ) ) ,
@@ -1791,7 +1830,7 @@ impl Context {
17911830
17921831 let mut new_slice = Vector :: new ( ) ;
17931832 self . slice_intrinsic_input ( & mut new_slice, slice) ?;
1794- // TODO(#2461 ): make sure that we have handled nested struct inputs
1833+ // TODO(#3364 ): make sure that we have handled nested struct inputs
17951834 let elem = new_slice
17961835 . pop_front ( )
17971836 . expect ( "There are no elements in this slice to be removed" ) ;
@@ -1831,7 +1870,7 @@ impl Context {
18311870 // they are attempting to insert at too large of an index.
18321871 // This check prevents a panic inside of the im::Vector insert method.
18331872 if index <= new_slice. len ( ) {
1834- // TODO(#2461 ): make sure that we have handled nested struct inputs
1873+ // TODO(#3364 ): make sure that we have handled nested struct inputs
18351874 new_slice. insert ( index, element) ;
18361875 }
18371876
@@ -1869,7 +1908,7 @@ impl Context {
18691908 // they are attempting to remove at too large of an index.
18701909 // This check prevents a panic inside of the im::Vector remove method.
18711910 let removed_elem = if index < new_slice. len ( ) {
1872- // TODO(#2461 ): make sure that we have handled nested struct inputs
1911+ // TODO(#3364 ): make sure that we have handled nested struct inputs
18731912 new_slice. remove ( index)
18741913 } else {
18751914 // This is a dummy value which should never be used if the appropriate
0 commit comments