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

Alexis Beingessner abeingessner at apple.com
Thu Dec 8 15:11:00 CST 2016

> On Dec 8, 2016, at 3:50 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> 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.

If this is considered a viable option, it's the one I want. Passing types without bounds checks into generic "safe" code shouldn't be this easy. You should need to explicitly wrap it up in something safe. And I really don't want the known-to-be-error-prone indexing model in concrete unsafe code.

> -- 
> -Dave
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

More information about the swift-evolution mailing list