[swift-evolution] [Pitch] Normalize Slice Types for Unsafe Buffers
Dave Abrahams
dabrahams at apple.com
Thu Dec 8 16:11:01 CST 2016
on Thu Dec 08 2016, Alexis Beingessner <swift-evolution at swift.org> wrote:
>> 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.
I don't think I agree, but that's a separate argument, about
UnsafeBufferPointer. This is about passing *untyped* memory without
bounds checks.
> 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
More information about the swift-evolution
mailing list