<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 24, 2016, at 11:02, David Waite &lt;<a href="mailto:david@alkaline-solutions.com" class="">david@alkaline-solutions.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">From "<font face="Helvetica Neue" class="">[swift-evolution] Notes from Swift core team 2016-03-23 design discussion”:</font><br class=""><blockquote type="cite" class=""><div class=""><div class="section" id="make-pointer-nullability-explicit-using-optional"><h3 class="" style="color: rgb(12, 55, 98); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; font-size: 1.1em; font-weight: normal; margin-top: 30px;">Make pointer nullability explicit using Optional<a class="headerlink" href="file:///Users/alexmartini/DevPubs%20Git%20Repositories/Swift%20Language%20Review/_build/html/LR_MeetingNotes/2016-03-23.html#make-pointer-nullability-explicit-using-optional" title="Permalink to this headline" style="visibility: hidden; font-weight: bold; text-decoration: none; color: rgb(167, 206, 56); padding-left: 5px;"></a></h3><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;"><a class="external reference" href="https://github.com/apple/swift-evolution/pull/219" style="font-weight: bold; text-decoration: none; color: rgb(137, 38, 1);">https://github.com/apple/swift-evolution/pull/219</a></p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">Biggest open issue is what to do with&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">UnsafeBufferPointer</span></tt>&nbsp;which has a base address and a count of the number of elements at that address. The most common use is to do fast things with an array. The problem is when you have an empty array.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">We have a statically initialized empty array, so this doesn’t apply to array. But slices and Cocoa arrays can do it.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">Half of the use cases are subscripting off of the buffer, so they don’t actually use the base address. They can’t actually subscript an empty array, but it’s not a syntax error — the loop is run zero times, so it doesn’t matter. The other half pass the pointers down to a C API that takes an address and count.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">Someone might expect that the base address doesn’t change when something is initialized.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">We can’t easily use the zero pointer because SIL already uses it for&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">nil</span></tt>. But there are issues with using the same representation as C to avoid bridging costs.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">We’re mapping two things in C onto one thing in Swift. In C, the buffer pointer would be&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">__nullable</span>&nbsp;<span class="pre">long</span>&nbsp;<span class="pre">*</span></tt>&nbsp;and the length is&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">ulong</span></tt>.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">Given everything else in the system, it’s more like pointer. We didn’t call it a buffer because that tends to imply ownership.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">Sketching out the state space:</p><table border="1" class="docutils" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; border: 0px; border-collapse: collapse; font-size: 14px;"><colgroup class=""><col width="30%" class=""><col width="26%" class=""><col width="26%" class=""><col width="17%" class=""></colgroup><tbody valign="top" class=""><tr class="row-odd"><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">Pointer</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">Length</td><td colspan="2" class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">Static type</td></tr><tr class="row-even"><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">null</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">0</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">UBP?</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">&nbsp;</td></tr><tr class="row-odd"><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">valid</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">&gt;= 0</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">UBP</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">&nbsp;</td></tr><tr class="row-even"><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">valid</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">&lt; 0</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">X</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">&nbsp;</td></tr><tr class="row-odd"><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">vull</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">!= 0</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">???</td><td class="" style="vertical-align: top; padding: 1px 8px 1px 5px; border-width: 0px 0px 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170);">&nbsp;</td></tr></tbody></table><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">This issue would go away if we got rid of the base address on&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">UnsafeBufferPointer</span></tt>, but that would get rid of a number of valid C operations like calling&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">memcopy</span></tt>.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">It seems like&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">withUnsafeBufferPointer</span></tt>&nbsp;should never produce nil. With that in mind, why should&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">UnsafeBufferPointer</span></tt>&nbsp;need to?</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">We do need a properly-aligned “valid” invalid pointer. LLVM makes assumptions about things being aligned.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">Dominant feedback on the list has been for people want something that round trips cleanly. Making the base address non-optional adds overhead and removes the ability to round trip.</p><p class="" style="color: rgb(51, 51, 51); font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif; text-align: justify;">It’s unfortunate that we don’t have a way to represent in the type system a buffer pointer that isn’t nullable, from within&nbsp;<tt class="literal docutils" style="background-color: rgb(226, 226, 226); font-size: 1em;"><span class="pre">withUnsafeBufferPointer</span></tt>&nbsp;which wouldn’t even call its closure if the buffer has a null base address.</p></div></div></blockquote><div class=""><div class=""><div class="section" id="make-pointer-nullability-explicit-using-optional"><div class="">In my mind UBP is primarily meant to be a collection. In that case, I imagine (nil, 0) as an input wouldn’t necessarily represent a nil UBP? - it could represent an empty UBP.&nbsp;</div><div class=""><br class=""></div><div class="">My question is whether a valid pointer, length 0 is a valid UBP or not - I have trouble imagining a API which wants a UBP which would differentiate this value over the (nil, 0) one and not have it either be an abuse of UBP (using it to transport just a pointer and not representing a buffer) or an error. I suspect it actually would be ok to always represent a length 0 UBP as having a nil base address.</div></div></div></div></div></div></blockquote><br class=""></div><div>I updated the proposal before it got accepted into the queue; the consensus was for the "round-trips cleanly" case. A (valid, 0) pair could still represent a range to replace in a C API, so canonicalizing to nil might be a bad idea.</div><div><br class=""></div><div>You can see the current version here as SE-0055:&nbsp;<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0055-optional-unsafe-pointers.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0055-optional-unsafe-pointers.md</a></div><div><br class=""></div><div>Jordan</div><br class=""></body></html>