> On Mar 18, 2016, at 9:49 AM, Jordan Rose <[email protected]> wrote:
>
>
>> On Mar 17, 2016, at 21:08 , Russ Bishop <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> I’m very much +1 on this idea.
>>
>>> On Mar 17, 2016, at 6:59 PM, Jordan Rose via swift-evolution
>>> <[email protected] <mailto:[email protected]>> wrote:
>>>
>>> <https://github.com/jrose-apple/swift-evolution/tree/optional-pointers#open-issue-unsafebufferpointer>Open
>>> Issue: UnsafeBufferPointer
>>>
>>> The type UnsafeBufferPointer represents a bounded typed memory region with
>>> no ownership or lifetime semantics; it is logically a bare typed pointer
>>> (its baseAddress) and a length (count). For a buffer with 0 elements,
>>> however, there's no need to provide the address of allocated memory, since
>>> it can't be read from. Previously this case would be represented as a nil
>>> base address and a count of 0.
>>>
>>> With optional pointers, this now imposes a cost on clients that want to
>>> access the base address: they need to consider the nil case explicitly,
>>> where previously they wouldn't have had to. There are several possibilities
>>> here, each with their own possible implementations:
>>>
>>> Like UnsafePointer, UnsafeBufferPointer should always have a valid base
>>> address, even when the count is 0. An UnsafeBufferPointer with a
>>> potentially-nil base address should be optional.
>>>
>>> UnsafeBufferPointer's initializer accepts an optional pointer and becomes
>>> failable, returning nil if the input pointer is nil.
>>>
>>> UnsafeBufferPointer's initializer accepts an optional pointer and
>>> synthesizes a non-null aligned pointer value if given nil as a base address.
>>>
>>> UnsafeBufferPointer's initializer only accepts non-optional pointers.
>>> Clients such as withUnsafeBufferPointermust synthesize a non-null aligned
>>> pointer value if they do not have a valid pointer to provide.
>>>
>>> UnsafeBufferPointer's initializer only accepts non-optional pointers.
>>> Clients using withUnsafeBufferPointermust handle a nil buffer.
>>>
>>> UnsafeBufferPointer should allow nil base addresses, i.e. the baseAddress
>>> property will be optional. Clients will need to handle this case explicitly.
>>>
>>> UnsafeBufferPointer's initializer accepts an optional pointer, but no other
>>> changes are made.
>>>
>>> UnsafeBufferPointer's initializer accepts an optional pointer.
>>> Additionally, any buffers initialized with a count of 0 will be
>>> canonicalized to having a base address of nil.
>>>
>>> I'm currently leaning towards option (2i). Clients that expect a pointer
>>> and length probably shouldn't require the pointer to be non-null, but if
>>> they do then perhaps there's a reason for it. It's also the least work.
>>>
>>> Chris (Lattner) is leaning towards option (1ii), which treats
>>> UnsafeBufferPointer similar to UnsafePointer while not penalizing the
>>> common case of withUnsafeBufferPointer.
>> What’s the use of an UnsafeBufferPointer with zero count? Semantically that
>> is making a claim that it can’t back up (“I have allocated memory at
>> location X” which isn’t compatible with the idea of “zero count/size").
>>
>> Without knowing more context I’d strongly favor (1i). If an array is empty
>> the natural expectation for withUnsafeBufferPointer is you get
>> UnsafeBufferPointer<Element>? = nil, which follows the behavior of the rest
>> of the language and things like guard let make it trivial to handle
>> properly. If someone really has a problem with it they can add
>> ifUnsafeBufferPointer() that returns a non-optional pointer and skips
>> executing the closure if the Array is empty (which is the behavior of your
>> standard for loop).
>
> The important use case here is that "array.withUnsafeBufferPointer" should
> always do something (i.e. it usually can't just skip the closure), and it
> turns out it's easiest if the zero-element case is treated the same as
> everything else. When converting over the standard library I found that very
> few of them wanted to do something different in the zero-element case, and
> then it would be bad to force Array to allocate memory just to not use it.
> That is, there aren't actually any clients interested in knowing whether the
> base address is valid, and all of the ones that do have to think about it
> (because they use it directly) aren't getting any value out of it.
>
> Jordan
Does optional chaining (ptr?.count ?? 0) or the guard check (guard let ptr =
ptr else { return }) impose a performance (or cognitive) burden here? I’m OK
with (2i), it just seems less Swift-ish than (1i).
I don’t use UnsafeBufferPointer a lot so I’ll happily live with whatever the
choice is.
Russ
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution