@@ -658,75 +658,76 @@ 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 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) )
683
713
}
714
+ None => array[ index] . clone ( ) ,
684
715
} ;
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
716
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 ) ;
715
719
}
716
720
}
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
+ }
718
726
}
719
727
}
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
+ } ;
725
730
726
- // Do nothing we only want dynamic checks for slices
727
- }
728
- _ => unreachable ! ( "ICE: expected array or slice type" ) ,
729
- }
730
731
Ok ( false )
731
732
}
732
733
0 commit comments