> On Mar 19, 2016, at 10:36, Chris Lattner <clatt...@apple.com> wrote:
> 
> 
> On Mar 18, 2016, at 9:49 AM, Jordan Rose via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> 
>> 
>>> On Mar 17, 2016, at 21:08 , Russ Bishop <xen...@gmail.com 
>>> <mailto:xen...@gmail.com>> wrote:
>>> 
>>> I’m very much +1 on this idea.
>>> 
>>>> On Mar 17, 2016, at 6:59 PM, Jordan Rose via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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.
> 
> Why would you have to allocate memory for this case?  The pointer only needs 
> to be non-null, not valid and dereferencable.  You could use the address of a 
> global or even 0x1.

I think it's important to preserve alignment; LLVM will sometimes optimize 
based on this.

Jordan

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to