Merge pull request #19991 from bradcray/unbounded-range-iters-not-infinite
Avoid infinite loops in (serial) unbounded range iterators
[reviewed by @stonea]
This changes the serial iterators for unbounded integral ranges such
that as they are about to run off the top or bottom of the range, they print
an error and halt rather than wrapping around to the extreme integer
on the other side as we have traditionally done. The approach taken is to
compute the near-maximum bound, exit the loop once it is reached to
avoid wrapping around within the loop itself, and then print an error if that
maximal value was reached. This conditional turns out to be important
because, without it, when we zipper unbounded ranges serially in the
"follower" position, we hit the halt.
It is tempting to add an additional
yield after the loop exits corresponding
to the most extreme index value (e.g.,
1:uint(8)..), but doing
so breaks our serial zippered loop optimization when an unbounded range
is used as a follower, as in
zip(whatever, 1..). It seemed preferable to
keep the performance and complain about falling off the end of the loop
126 than to get this most extreme value.
Both of the cases above in which the unbounded range is used as a follower
could arguably by seen as (additional) motivation for supporting distinct
iterators for serial standalone vs. follower iterators (the main traditional one
being to give users the tools to write their own unbounded follower iterators).
For unbounded ranges over enums and bools, the process is similar, but
slightly different since the problem of wraparound doesn't exist (well...
for most reasonably sized enums anyway). We just iterate through all the
values and then return without an error.
Added some tests of various upward and downward iterations over unbounded
ranges of ints, enums, bools x strided vs. non-.
Modified Files: A test/types/range/unbounded/unboundedBoolEnum.chpl