[swift-evolution] [Pitch] Normalize Slice Types for Unsafe Buffers

Dave Abrahams dabrahams at apple.com
Thu Dec 8 14:50:07 CST 2016

on Thu Dec 08 2016, Ben Cohen <ben_cohen-AT-apple.com> wrote:

>> On Dec 2, 2016, at 8:27 PM, Nate Cook <natecook at gmail.com> wrote:
>>> On Dec 2, 2016, at 2:12 PM, Ben Cohen via swift-evolution
>>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
>>> wrote:
>>>> On Dec 1, 2016, at 11:33 PM, Nate Cook via swift-evolution
>>>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
>>>> wrote:
>>>> 3) Make all buffer pointers their own slices but use a different
>>>> index type. If the indices were just wrapped pointers, that would
>>>> handle the index sharing without needing an additional property on
>>>> the buffer. We could also maintain integer-based stridable
>>>> conformance (which greatly simplifies index arithmetic), since the
>>>> indices would just offset by a byte for raw buffers or a stride
>>>> for typed buffers.
>>> Unfortunately, switching to non-integer indices would change this
>>> from being mildly source-breaking to being extremely
>>> source-breaking, as there’s lots of code out there using buffers
>>> today indexing them with integers (including integer literals).
>>> The big win with UnsafeBufferPointer having an integer index is
>>> it’s a drop-in replacement for arrays, so when you hit a
>>> performance problem using an array you can quickly switch to using
>>> a buffer under most circumstances instead without having to change
>>> much of your code – including code that uses for i in
>>> 0..<myArray.count, of which there is a lot out there in the
>>> wild. Switching to an opaque index would break anyone doing that.
>> It is definitely very source-breaking, though with relatively simple fixits:
>> 	buf[0] ---> buf[buf.startIndex]
>> 	buf[3] ---> buf[buf.startIndex + 3]
>> 	buf[i] ---> buf[buf.startIndex + i]
>> Any integer arithmetic happening outside the subscript could be left
>> unchanged. If that cost isn't worth the benefit, then making
>> UnsafeRawBufferPointer use Slice as its slice type is probably the
>> best way to resolve that issue.
>> Nate
> The fixits aren’t quite that simple for slices, though:
> 	let slice = buf[3..<6]
> 	slice[3] —> slice[slice.startIndex + 0] // fixit would somehow need to know this is 0 not 3
> 	slice[i] —> slice[slice.startIndex + ??] // or even need to
> know this is, erm, I haven’t had enough coffee this morning
> The other downside is it would thwart speculatively switching an Array
> to an UnsafeBuffer to see if that was a bottleneck, then switching
> back.
>> On Dec 1, 2016, at 11:33 PM, Nate Cook via swift-evolution <swift-evolution at swift.org> wrote:
>> 1) Switch to using Slice as a wrapper for UnsafeRawBufferPointer.
> Based on the above, it seems like this is the least bad option, and we
> need to do this ASAP as currently UnsafeRawBufferPointer is
> non-compliant with the requirements of slicing and needs changing
> before it’s more widely adopted.

Or we could say that UnsafeRawBufferPointer isn't a Collection.  Making
it a Collection in the first place has always seemed suspect to me.


More information about the swift-evolution mailing list