@@ -658,75 +658,76 @@ impl Context {
658658 store_value : Option < ValueId > ,
659659 ) -> Result < bool , RuntimeError > {
660660 let index_const = dfg. get_numeric_constant ( index) ;
661- match dfg. type_of_value ( array) {
662- Type :: Array ( _, _) => {
663- match self . convert_value ( array, dfg) {
664- AcirValue :: Var ( acir_var, _) => {
665- return Err ( RuntimeError :: InternalError ( InternalError :: UnExpected {
666- expected : "an array value" . to_string ( ) ,
667- found : format ! ( "{acir_var:?}" ) ,
668- call_stack : self . acir_context . get_call_stack ( ) ,
669- } ) )
670- }
671- AcirValue :: Array ( array) => {
672- if let Some ( index_const) = index_const {
673- let array_size = array. len ( ) ;
674- let index = match index_const. try_to_u64 ( ) {
675- Some ( index_const) => index_const as usize ,
676- None => {
677- let call_stack = self . acir_context . get_call_stack ( ) ;
678- return Err ( RuntimeError :: TypeConversion {
679- from : "array index" . to_string ( ) ,
680- into : "u64" . to_string ( ) ,
681- call_stack,
682- } ) ;
661+ let value_type = dfg. type_of_value ( array) ;
662+ let ( Type :: Array ( element_types, _) | Type :: Slice ( element_types) ) = & value_type else {
663+ unreachable ! ( "ICE: expected array or slice type" ) ;
664+
665+ } ;
666+
667+ // TODO(#3188): Need to be able to handle constant index for slices to seriously reduce
668+ // constraint sizes of nested slices
669+ // This can only be done if we accurately flatten nested slices as otherwise we will reach
670+ // index out of bounds errors. If the slice is already flat then we can treat them similarly to arrays.
671+ if matches ! ( value_type, Type :: Slice ( _) )
672+ && element_types. iter ( ) . any ( |element| element. contains_slice_element ( ) )
673+ {
674+ return Ok ( false ) ;
675+ }
676+
677+ match self . convert_value ( array, dfg) {
678+ AcirValue :: Var ( acir_var, _) => {
679+ return Err ( RuntimeError :: InternalError ( InternalError :: UnExpected {
680+ expected : "an array value" . to_string ( ) ,
681+ found : format ! ( "{acir_var:?}" ) ,
682+ call_stack : self . acir_context . get_call_stack ( ) ,
683+ } ) )
684+ }
685+ AcirValue :: Array ( array) => {
686+ if let Some ( index_const) = index_const {
687+ let array_size = array. len ( ) ;
688+ let index = match index_const. try_to_u64 ( ) {
689+ Some ( index_const) => index_const as usize ,
690+ None => {
691+ let call_stack = self . acir_context . get_call_stack ( ) ;
692+ return Err ( RuntimeError :: TypeConversion {
693+ from : "array index" . to_string ( ) ,
694+ into : "u64" . to_string ( ) ,
695+ call_stack,
696+ } ) ;
697+ }
698+ } ;
699+ if self . acir_context . is_constant_one ( & self . current_side_effects_enabled_var ) {
700+ // Report the error if side effects are enabled.
701+ if index >= array_size {
702+ let call_stack = self . acir_context . get_call_stack ( ) ;
703+ return Err ( RuntimeError :: IndexOutOfBounds {
704+ index,
705+ array_size,
706+ call_stack,
707+ } ) ;
708+ } else {
709+ let value = match store_value {
710+ Some ( store_value) => {
711+ let store_value = self . convert_value ( store_value, dfg) ;
712+ AcirValue :: Array ( array. update ( index, store_value) )
683713 }
714+ None => array[ index] . clone ( ) ,
684715 } ;
685- if self
686- . acir_context
687- . is_constant_one ( & self . current_side_effects_enabled_var )
688- {
689- // Report the error if side effects are enabled.
690- if index >= array_size {
691- let call_stack = self . acir_context . get_call_stack ( ) ;
692- return Err ( RuntimeError :: IndexOutOfBounds {
693- index,
694- array_size,
695- call_stack,
696- } ) ;
697- } else {
698- let value = match store_value {
699- Some ( store_value) => {
700- let store_value = self . convert_value ( store_value, dfg) ;
701- AcirValue :: Array ( array. update ( index, store_value) )
702- }
703- None => array[ index] . clone ( ) ,
704- } ;
705716
706- self . define_result ( dfg, instruction, value) ;
707- return Ok ( true ) ;
708- }
709- }
710- // If there is a predicate and the index is not out of range, we can directly perform the read
711- else if index < array_size && store_value. is_none ( ) {
712- self . define_result ( dfg, instruction, array[ index] . clone ( ) ) ;
713- return Ok ( true ) ;
714- }
717+ self . define_result ( dfg, instruction, value) ;
718+ return Ok ( true ) ;
715719 }
716720 }
717- AcirValue :: DynamicArray ( _) => ( ) ,
721+ // If there is a predicate and the index is not out of range, we can directly perform the read
722+ else if index < array_size && store_value. is_none ( ) {
723+ self . define_result ( dfg, instruction, array[ index] . clone ( ) ) ;
724+ return Ok ( true ) ;
725+ }
718726 }
719727 }
720- Type :: Slice ( _) => {
721- // TODO(#3188): Need to be able to handle constant index for slices to seriously reduce
722- // constraint sizes of nested slices
723- // This can only be done if we accurately flatten nested slices as other we will reach
724- // index out of bounds errors.
728+ AcirValue :: DynamicArray ( _) => ( ) ,
729+ } ;
725730
726- // Do nothing we only want dynamic checks for slices
727- }
728- _ => unreachable ! ( "ICE: expected array or slice type" ) ,
729- }
730731 Ok ( false )
731732 }
732733
0 commit comments