[swift-evolution] Proposal: One-past-end array pointers and convertibility of nil for interaction with C APIs

Árpád Goretity arpad.goretity at gmail.com
Wed Dec 23 20:15:52 CST 2015


> The & operator isn't exactly an address-of operator

Yes, exactly! And that's why I think it should not sometimes work like that.

>From what I can tell, when passing the address of an array element to a C
function via unsafe pointers, no temporary is created (as it is the case
when passing an inout parameter to other Swift functions).

By the way, passing the array as inout also works in my particular case; it
doesn't address the issue of one-past-end pointers, though.


On Thu, Dec 24, 2015 at 3:01 AM, Árpád Goretity <arpad.goretity at gmail.com>
wrote:

> > The & operator isn't exactly an address-of operator
>
> Yes, exactly! And that's why I think it should not sometimes work like
> that.
>
> From what I can tell, when passing the address of an array element to a C
> function via unsafe pointers, no temporary is created (as it is the case
> when passing an inout parameter to other Swift functions).
>
>
> On Thu, Dec 24, 2015 at 2:48 AM, Félix Cloutier <
> felix.cloutier.1 at ens.etsmtl.ca> wrote:
>
>> The & operator isn't exactly an address-of operator. Does &arr[0] even
>> return a pointer to the inner buffer? When you use & with properties (and
>> possibly with subscripts as well), Swift may create a local, copy the
>> property value to it, pass a pointer to that local, and copy back the
>> output to the property.
>>
>> Anyway, you are probably looking for
>> Array.withUnsafe(Mutable?)BufferPointer:
>>
>> arr.withUnsafeMutableBufferPointer { foo($0, $0.count) }
>>
>> Le 23 déc. 2015 à 20:35:09, Árpád Goretity via swift-evolution <
>> swift-evolution at swift.org> a écrit :
>>
>> Hi everyone,
>>
>> I was recently trying to use a C API (LLVM for the record) that required
>> passing an array to a function in the form of a pointer and a size. I
>> couldn't find a straightforward way to pass a null pointer to the function
>> in question conditionally (when the array is empty), since the following –
>> simplified – code doesn't currently typecheck:
>>
>>     // C function with signature: void foo(T *ptr, unsigned size)
>>     // imported into Swift as: (UnsafeMutablePointer<T>, UInt32) -> ()
>>     var arr: [T] = []
>>     foo(arr.count > 0 ? &arr[0] : nil, UInt32(arr.count))
>>
>> The error is: result values in '? :' expression have mismatching types
>> 'inout T' and '_'
>>
>> This does not make sense since although `nil` is typeless by itself, its
>> concrete type should still be able to be inferred from the context (just
>> like it is inferred correctly if one writes
>>
>>     condition ? 1 as Optional<Int> : nil
>>
>> which is an analogous scenario.)
>>
>> Since the inout operator (&) can only be used in function call arguments
>> (so it's not exactly C's address-of), I believe that there's no easy way of
>> elegantly passing a null pointer when the array is empty. (Yes, I could
>> write two almost-identical calls, but meh…) And even if there is one (and
>> I'm just missing it), the fact that the above code does not work seems
>> inconsistent to me.
>>
>> I also realized that this specific issue generalizes to the (in)ability
>> of passing one-past-end pointers – which would be equally valid and even
>> more convenient in the above case, as the callee does not dereference the
>> passed pointer when the count is 0, but in general, it can be applied to
>> functions accepting [begin, end + 1) ranges.
>>
>> The problem here is that a one-past-end pointer does not reside at a
>> valid index (pretty much by definition), so bounds checking kicks in and
>> kills the program.
>>
>> My proposed solutions:
>>
>>  – Extend type inference for unsafe pointers and nil, so that when a
>> value is passed by address to a function, it's not only the result of an
>> &-expression that has its type inferred to be (or implicitly converted to)
>> Unsafe[Mutable]Pointer, but if there's a nil somewhere around, such as the
>> one in the example above, it gets promoted to that type too, just like NULL
>> in C or nullptr in C++.
>>
>>  – Stop overloading the inout '&' operator and using it for C-style
>> address-of operations. I could imagine a similar, but distinct operator or
>> even a library function (something along the lines of unsafeAddressOf) that
>> specifically yields the physical address of its operand as an unsafe C
>> pointer, and which is thus first-class in the sense that it may be used
>> anywhere other expressions may be, not just as immediate call arguments.
>>
>>  – Make array bounds checking more lenient when passing pointers to array
>> elements into C functions. Bounds checking should, in these cases, allow
>> indexing the one-past-end element of an array if (and only if) it is the
>> argument of the address-of operator.
>>
>> Comments and questions are welcome (you might need clarification, as it's
>> 2:35 AM here when I'm writing this…)
>>
>> Cheers,
>>
>> --
>> Author of the Sparkling language
>> http://h2co3.org/
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>>
>
>
> --
> Author of the Sparkling language
> http://h2co3.org/
>
>


-- 
Author of the Sparkling language
http://h2co3.org/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151224/1c4ee984/attachment.html>


More information about the swift-evolution mailing list