PartialRangeFrom
is not a BidirectionalCollection
, so calling reversed()
on it does not produce a ReversedCollection
.
Instead it produces an Array
.
The program hangs while attempting to materialize that array. This is exactly the same behavior you would see when converting any other very long (or endless) sequence into an array.
• • •
To “fix” the behavior, we could introduce a deprecated overload:
extension PartialRangeFrom where Bound: Strideable, Bound.Stride: SignedInteger {
@available(*, deprecated, message: "Cannot reverse a PartialRangeFrom")
func reversed() -> [Bound] { fatalError() }
}
That way attempting to call reversed
on a PartialRangeFrom
would give a compile-time warning and trap at runtime, instead of hanging.
The hang would still happen if reversed
was called on such a value in a generic context, but such is life.
• • •
Interestingly, this code traps at runtime for me (Xcode 11.3.1, Swift 5.1.3):
let a = (1 as Int8)...
let b = a.reversed() // Execution was interrupted, reason: EXC_BAD_INSTRUCTION
print(b.count)
And indeed so does this:
let a = Array((1 as Int8)...)
Or even this:
let a = ((1 as Int8)...).max()
The implication is clearly that partial ranges in fact model truly unbounded, one-sided intervals, not restricted to the set of representable values for the element type.