<div dir="ltr"><div style="font-size:12.8px">Thanks for your answer!</div><span class="im" style="font-size:12.8px"><div><br></div>&gt; <span style="font-size:12.8px">I think the thing to do is to make two calls:</span><div><span style="font-size:12.8px"><br></span></div></span><div style="font-size:12.8px"><span style="font-size:12.8px">Eeeek, that&#39;s exactly what I wanted to avoid (which I actually think is the worst possible solution).</span></div><div style="font-size:12.8px"><span style="font-size:12.8px"><br></span></div><div style="font-size:12.8px"><span style="font-size:12.8px">&gt; </span><span style="font-size:12.8px">The inout-to-pointer is only available to function argument expressions; it&#39;s not even considered in a ternary expression here.</span></div><div style="font-size:12.8px"><span style="font-size:12.8px"><br></span></div><div style="font-size:12.8px"><span style="font-size:12.8px">Yes, I realized that (in fact I think the diagnostic makes this quite clear). I understand *why* it does not currently work, I&#39;m merely suggesting that I think it *should* work. (It might be too hard to implement, just my opinion.)</span></div><div style="font-size:12.8px"><span style="font-size:12.8px"><br></span></div><div style="font-size:12.8px"><span style="font-size:12.8px">&gt; </span><span style="font-size:12.8px">In general, we can&#39;t support fully first-class pointers into managed Swift entities like Array and properties, without breaking the encapsulation of those abstractions.</span></div><div style="font-size:12.8px"><span style="font-size:12.8px"><br></span></div><div style="font-size:12.8px"><span style="font-size:12.8px">Yes, that&#39;s kind of obvious – what I am actually trying to suggest is that unsafe is already unsafe, so it might be OK to &quot;break the encapsulation&quot;, for example by returning a pointer to the internal buffer without introducing a temporary.</span></div><div style="font-size:12.8px"><span style="font-size:12.8px"><br></span></div><div style="font-size:12.8px"><span style="font-size:12.8px">However, if you agree about sharply distinguishing Swift inout and unsafe + C address of (possibly in a way that my examples would work with the new unsafe address-of operator), I&#39;m happy to narrow down my proposal to that specific case.</span></div><div style="font-size:12.8px"><span style="font-size:12.8px"><br></span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 24, 2015 at 9:43 PM, Árpád Goretity <span dir="ltr">&lt;<a href="mailto:arpad.goretity@gmail.com" target="_blank">arpad.goretity@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Thanks for your answer!</div><span class=""><div><br></div>&gt; <span style="font-size:12.8px">I think the thing to do is to make two calls:</span><div><span style="font-size:12.8px"><br></span></div></span><div><span style="font-size:12.8px">Eeeek, that&#39;s exactly which I wanted to avoid (and which I think is the worst possible solution).</span></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 24, 2015 at 5:26 PM, Joe Groff <span dir="ltr">&lt;<a href="mailto:jgroff@apple.com" target="_blank">jgroff@apple.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On Dec 23, 2015, at 5:35 PM, Árpád Goretity via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br><div><div dir="ltr">Hi everyone,<div><br></div><div>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&#39;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&#39;t currently typecheck:</div><div><br></div><div>    // C function with signature: void foo(T *ptr, unsigned size)</div><div>    // imported into Swift as: (UnsafeMutablePointer&lt;T&gt;, UInt32) -&gt; ()</div><div>    var arr: [T] = []</div><div>    foo(arr.count &gt; 0 ? &amp;arr[0] : nil, UInt32(arr.count))</div><div><br></div><div>The error is: result values in &#39;? :&#39; expression have mismatching types &#39;inout T&#39; and &#39;_&#39; </div></div></div></blockquote><div><br></div></span><div>The diagnostic here sucks. The inout-to-pointer is only available to function argument expressions; it&#39;s not even considered in a ternary expression here, so the type checker can&#39;t find any way to match &#39;nil&#39; and an inout.</div><span><br><blockquote type="cite"><div><div dir="ltr"><div>Since the inout operator (&amp;) can only be used in function call arguments (so it&#39;s not exactly C&#39;s address-of), I believe that there&#39;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&#39;m just missing it), the fact that the above code does not work seems inconsistent to me.</div><div><div><br></div><div>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.</div><div><br></div><div>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.</div></div></div></div></blockquote><div><br></div></span><div>Past-the-end indices are valid pointers (and valid in Swift collections in general). That&#39;s not the problem. `&amp;arr[0]` fails because it&#39;s providing a temporary buffer connected only to the *element* &amp;arr[0], rather than a buffer representing the entire array. This won&#39;t do what you expect for any Swift array, even if it&#39;s non-empty.</div><div><br></div><div>In general, we can&#39;t support fully first-class pointers into managed Swift entities like Array and properties, without breaking the encapsulation of those abstractions. We can provide scoped operations like `withUnsafePointer` that give you a pointer to a possibly-temporary buffer that represents the value of that array or value for the duration of a block. When you say `CFunctionThatTakesPointer(&amp;a)`, Swift&#39;s really wrapping that call in the equivalent of `withUnsafeMutableBufferPointer` on your behalf. You can see how that would be problematic if the wrapping needs to be conditional, such as if it appeared in a ternary or &amp;&amp;/|| expression. I think the thing to do is to make two calls:</div><div><br></div><div>if arr.empty {</div><div>  foo(nil, 0)</div><div>} else {</div><div>  foo(&amp;arr, arr.count)</div><div>}</div><div><br></div><div>since preparing the buffer for the pointer itself isn&#39;t necessarily free, and you&#39;d want to avoid that work if you don&#39;t need it.</div><div><br></div><div>It might be OK to have the pointer produced for an empty array be null to begin with, which would avoid the need for this conditional at all. In most cases, you can&#39;t safely dereference a pointer to nothing anyway. I&#39;m also sympathetic to the idea of disconnecting &quot;address-of&quot; and &quot;inout&quot;, since it often leads to confusion like this.</div><span><font color="#888888"><div><br></div><div>-Joe</div><br></font></span><blockquote type="cite"><div><span><div dir="ltr"><div><div>My proposed solutions:</div><div><br></div><div> – Extend type inference for unsafe pointers and nil, so that when a value is passed by address to a function, it&#39;s not only the result of an &amp;-expression that has its type inferred to be (or implicitly converted to) Unsafe[Mutable]Pointer, but if there&#39;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++.</div><div><br></div><div> – Stop overloading the inout &#39;&amp;&#39; 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.</div><div><br></div><div> – 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.</div><div><br></div><div>Comments and questions are welcome (you might need clarification, as it&#39;s 2:35 AM here when I&#39;m writing this…)</div><div><br></div><div>Cheers,</div><div><br></div>-- <br><div><div dir="ltr"><font face="monospace" size="3">Author of the Sparkling language</font><div><font face="monospace" size="3"><a href="http://h2co3.org/" target="_blank">http://h2co3.org/</a><br></font></div><div><font face="monospace" size="3"><br></font></div></div></div>
</div></div>
</span><span><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=RoDF4MveSEMYBIqIJA6ub1g8cOZ-2BVYvqV-2FqygPhjPn9zj0ys8nJu9ylq-2BdpicsJKuLXKmY0ceHMJ1MYMJ0AbZy99rB0ShOU1MkVJeonVWJIqQ8xVyx-2BpKLr-2FXrmJFOmAW-2BItyhWolW0IfGKA9ynicamDMibuiZq-2BnDKyd-2BAHd3p9ZZZat8eWK-2BJcIZvufPYvT9igASz4wKx86pMeUKkh2SadB0a6ayWr8VFe5VSNOaw-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></span></div></blockquote></div><br></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div><div dir="ltr"><font color="#000000" face="monospace" size="3">Author of the Sparkling language</font><div><font color="#000000" face="monospace" size="3"><a href="http://h2co3.org" target="_blank">http://h2co3.org/</a><br></font></div><div><font color="#000000" face="monospace" size="3"><br></font></div></div></div>
</div>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><font color="#000000" face="monospace" size="3">Author of the Sparkling language</font><div><font color="#000000" face="monospace" size="3"><a href="http://h2co3.org" target="_blank">http://h2co3.org/</a><br></font></div><div><font color="#000000" face="monospace" size="3"><br></font></div></div></div>
</div>