RangeFrom and panic at upperbound-1

When iterating a RangeFrom<u8>, the last accessible value is 254 and not 255 (and more generally MAX-1 is the last value for an integral type)
I digged in the source code that it is because of the Iterator::next() of ops::RangeFrom which computes the next value before returning the old one : 255 cannot be returned since 255+1 will panic just before.
I understand this is more or less how next() works, but in a RangeInclusiveIterator<u8>, the "exhausted" field makes it possible to iterate up to 255.
So, what is the reason for RangeFrom not to go as far as RangeInclusive ?
Is this by design for a specific purpose, or a legacy behaviour that should not be overriden ?
[edit]RangeTo => RangeFrom[/edit]

Your question bounces between RangeFrom and RangeTo. RangeTo is exclusive on the upper bound by design. That design is not based on RangeFrom's implementation details.

For RangeFrom, the maximum can be returned, but an overflow will happen just before the return. That can be a panic or it can wrap around, based on compilation flags. (The docs say "debug or release", but that only reflects the defaults for the actual flag.)

It's documented to happen at that point, so changing it would be a breaking change.

Here's an example of it returning 255 and continuing after overflow.

(Sorry for the RangeFrom/RangeTo typo, I fixed it)

  • about the overflow/wrapping , according to Debug/Release, I am aware of that, I just assume that Debug is the safest option to describe intended code (I accept the overflow panic as expected behaviour)
  • yes, the unreachable MAX is documented :

Note also that overflow happens earlier than you might assume: the overflow happens in the call to next that yields the maximum value, as the range must be set to a state to yield the next value.

  • my question is about why it was designed with this limitation. (compared to RangeInclusiveIterator)

I am currently investigating rust behaviour in corner cases and often, the reason behind a design choice is a good way to get very clever information (and sometimes it is just an unwise decision)

1 Like

That I don't know off the top of my head. That documentation comes from here, documenting as intended behavior existing since 1.0 or before. The current design of the unstable Step trait seems like a motivator (beyond backwards stability), but that's where I stopped digging.

1 Like

My best guess is that getting close to the upper bound of a RangeFrom is the symptom of something going wrong; the fact that the limit is MAX-1 instead of MAX should not be a real problem itself, and we can assume that reaching MAX-1 is already a degenerate situation : a RangeInclusive would have been a wiser choice for such a running code.
And under this assumption, why bother with the "exhausted" trick ? Let's keep the RangeFrom code simpler (and faster).

You'd probably be interested in reading this RFC:

Basically, it's now considered a mistake that the types for the intervals and the actual iterators for those intervals were made the same type.

1 Like