@@ -658,75 +658,74 @@ impl Context {
658
658
store_value : Option < ValueId > ,
659
659
) -> Result < bool , RuntimeError > {
660
660
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 other we will reach
670
+ // index out of bounds errors.
671
+ if element_types. iter ( ) . any ( |element| element. contains_slice_element ( ) ) {
672
+ return Ok ( false ) ;
673
+ }
674
+
675
+ match self . convert_value ( array, dfg) {
676
+ AcirValue :: Var ( acir_var, _) => {
677
+ return Err ( RuntimeError :: InternalError ( InternalError :: UnExpected {
678
+ expected : "an array value" . to_string ( ) ,
679
+ found : format ! ( "{acir_var:?}" ) ,
680
+ call_stack : self . acir_context . get_call_stack ( ) ,
681
+ } ) )
682
+ }
683
+ AcirValue :: Array ( array) => {
684
+ if let Some ( index_const) = index_const {
685
+ let array_size = array. len ( ) ;
686
+ let index = match index_const. try_to_u64 ( ) {
687
+ Some ( index_const) => index_const as usize ,
688
+ None => {
689
+ let call_stack = self . acir_context . get_call_stack ( ) ;
690
+ return Err ( RuntimeError :: TypeConversion {
691
+ from : "array index" . to_string ( ) ,
692
+ into : "u64" . to_string ( ) ,
693
+ call_stack,
694
+ } ) ;
695
+ }
696
+ } ;
697
+ if self . acir_context . is_constant_one ( & self . current_side_effects_enabled_var ) {
698
+ // Report the error if side effects are enabled.
699
+ if index >= array_size {
700
+ let call_stack = self . acir_context . get_call_stack ( ) ;
701
+ return Err ( RuntimeError :: IndexOutOfBounds {
702
+ index,
703
+ array_size,
704
+ call_stack,
705
+ } ) ;
706
+ } else {
707
+ let value = match store_value {
708
+ Some ( store_value) => {
709
+ let store_value = self . convert_value ( store_value, dfg) ;
710
+ AcirValue :: Array ( array. update ( index, store_value) )
683
711
}
712
+ None => array[ index] . clone ( ) ,
684
713
} ;
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
- } ;
705
714
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
- }
715
+ self . define_result ( dfg, instruction, value) ;
716
+ return Ok ( true ) ;
715
717
}
716
718
}
717
- AcirValue :: DynamicArray ( _) => ( ) ,
719
+ // If there is a predicate and the index is not out of range, we can directly perform the read
720
+ else if index < array_size && store_value. is_none ( ) {
721
+ self . define_result ( dfg, instruction, array[ index] . clone ( ) ) ;
722
+ return Ok ( true ) ;
723
+ }
718
724
}
719
725
}
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.
726
+ AcirValue :: DynamicArray ( _) => ( ) ,
727
+ } ;
725
728
726
- // Do nothing we only want dynamic checks for slices
727
- }
728
- _ => unreachable ! ( "ICE: expected array or slice type" ) ,
729
- }
730
729
Ok ( false )
731
730
}
732
731
0 commit comments