Badly. LLVM chokes on all chain-like iterators.
This would be ideal, yet the issue I mentioned is 6 years old so I have some doubts it will ever be "fixed".
I think that beyond of the one-off variation -- or for the more generic case of a multi-chain iterators, of the monotonic increment -- there's also the issue of code bloat: splitting a loop involves copy/pasting the loop body as many times as you split.
Sure, this may reveal optimization opportunities within the loop body afterwards -- by specializing its context -- but it may also not, and thus you'd need to develop a set of heuristics not dissimilar to inlining/constant-propagation heuristics to gauge whether it's worth splitting or not.
I wouldn't necessarily abandon hope, but after 6 years I think we're better off special-casing RangeInclusiveIter for now: we can always simplify the implementation later on if LLVM catches up!
BTW, I just realized we may need a 3rd case in the enum:
enum RangeInclusiveIterImpl<T> {
// Akin to `start..end`.
Exclusive { start: T, end: T },
// Akin to `(start..end).map(|e| e + 1)`.
ExclusiveShifted { start: T, end: T },
// Akin to start..=end.
Inclusive { start: T, end: T },
}
The new case (shifted) being used to represent ranges of the form x..=MAX where end cannot be incremented, but the whole range can be mapped to (x - 1)..MAX and each element incremented by 1 prior to being returned.
This ensures that Inclusive is only used for full ranges, when start cannot be decremented and end cannot be incremented -- so it first needs to return start, and then be converted to ExclusiveShifted { start, end } which will take care of iterating over (start - 1)..end and incrementing each returned value.