@@ -792,10 +792,23 @@ def init(self, expr_reg: Value, target_type: RType, reverse: bool) -> None:
792792 # for the for-loop. If we are inside of a generator function, spill these into the
793793 # environment class.
794794 self .expr_target = builder .maybe_spill (expr_reg )
795+ if (
796+ is_tuple_rprimitive (expr_reg .type )
797+ or is_str_rprimitive (expr_reg .type )
798+ or is_bytes_rprimitive (expr_reg .type )
799+ or is_frozenset_rprimitive (expr_reg .type )
800+ ):
801+ self .length_reg = builder .maybe_spill (self .load_len (self .expr_target ))
802+ else :
803+ self .length_reg = None
795804 if not reverse :
796805 index_reg : Value = Integer (0 , c_pyssize_t_rprimitive )
797806 else :
798- index_reg = builder .builder .int_sub (self .load_len (self .expr_target ), 1 )
807+ if self .length_reg is not None :
808+ len_val = builder .read (self .length_reg )
809+ else :
810+ len_val = self .load_len (self .expr_target )
811+ index_reg = builder .builder .int_sub (len_val , 1 )
799812 self .index_target = builder .maybe_spill_assignable (index_reg )
800813 self .target_type = target_type
801814
@@ -814,9 +827,13 @@ def gen_condition(self) -> None:
814827 second_check = BasicBlock ()
815828 builder .add_bool_branch (comparison , second_check , self .loop_exit )
816829 builder .activate_block (second_check )
817- # For compatibility with python semantics we recalculate the length
818- # at every iteration.
819- len_reg = self .load_len (self .expr_target )
830+ if self .length_reg is None :
831+ # For compatibility with python semantics we recalculate the length
832+ # at every iteration.
833+ len_reg = self .load_len (self .expr_target )
834+ else :
835+ # (unless input is immutable type).
836+ len_reg = builder .read (self .length_reg , line )
820837 comparison = builder .binary_op (builder .read (self .index_target , line ), len_reg , "<" , line )
821838 builder .add_bool_branch (comparison , self .body_block , self .loop_exit )
822839
0 commit comments