<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 Aug 20, 2016, at 4:02 AM, Michael Ferenduros via swift-users &lt;<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On 20 Aug 2016, at 07:25, Andrew Trick &lt;<a href="mailto:atrick@apple.com" class="">atrick@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><br class="Apple-interchange-newline">On Aug 19, 2016, at 4:49 PM, Michael Ferenduros via swift-users &lt;<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">On Aug 18, 2016, at 12:28 AM, Quinn The Eskimo! via swift-users &lt;swift-users at<span class="Apple-converted-space">&nbsp;</span><a href="http://swift.org/" class="">swift.org</a>&gt; wrote:<span class="Apple-converted-space">&nbsp;</span><br class=""><br class=""><br class="">On 17 Aug 2016, at 18:55, Martin R via swift-users &lt;swift-users at<span class="Apple-converted-space">&nbsp;</span><a href="http://swift.org/" class="">swift.org</a>&gt; wrote:<span class="Apple-converted-space">&nbsp;</span><br class=""><br class=""><blockquote type="cite" class="">- Are both solutions correct, should one be preferred, or are both wrong?<span class="Apple-converted-space">&nbsp;</span><br class=""></blockquote><br class="">Your `withMemoryRebound` solution is correct.<span class="Apple-converted-space">&nbsp;</span><br class=""></blockquote>Absolutely, withMemoryRebound is always safe. You can use it whenever you just need to reinterpret memory at a call site and know the number of values stored that memory location. In this case it’s “easy" because you’re dealing a single sockaddr_in. The UnsafeRawPointer proposal is the definitive reference<span class="Apple-converted-space">&nbsp;</span><br class=""><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md</a><span class="Apple-converted-space">&nbsp;</span>&lt;<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md</a>&gt; But this migration guide is more approachable… it’s still WIP:<span class="Apple-converted-space">&nbsp;</span><br class=""><a href="https://gist.github.com/atrick/0283ae0e284610fd21ad6ed3f454a585" class="">https://gist.github.com/atrick/0283ae0e284610fd21ad6ed3f454a585</a><br class=""></blockquote><br class="">I’m running into the same issues, which is making me wonder withMemoryRebound - socket functions expect an UnsafePointer&lt;sockaddr&gt;, but the thing pointed to can actually be larger than a sockaddr (eg. sockaddr_in6 or sockaddr_storage). Is withMemoryRebound safe to use to cast pointers to differently-sized structures? In the case of UnsafeMutablePointer&lt;sockaddr&gt; it seems like you’re lying to the API about what memory may be modified… But if withMemoryRebound isn’t about providing that guarantee, what does it actually do vs eg. a dumb cast via OpaquePointer?<br class=""></div></div></blockquote><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Good point. I replied too hastily, but you’re about to find out why I didn’t go into details…</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class="">As you can&nbsp;<a href="https://github.com/apple/swift/blob/master/stdlib/public/core/UnsafePointer.swift.gyb#L371" class="">see</a>, withMemoryRebound(to: T.self, capacity: count) actually does this:</div><div class="">- (re)binds memory to `count` `T` values</div><div class="">- executes the closure</div><div class="">- (re)binds memory to `count` `Pointee` values</div><div class=""><br class=""></div><div class="">For `count == 1` and `MemoryLayout&lt;T&gt;.size &lt; MemoryLayout&lt;Pointee&gt;.size` this is valid and safe for "compatible" structs. The precondition on `withMemoryRebound` states that `T` must be layout compatible with `Pointee`.</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; aggregates (tuples, array storage, and structs), are layout</div><div class="">&nbsp; compatible with larger aggregates of the same kind if their common</div><div class="">&nbsp; elements are mutually layout compatible.</div><div class=""><br class=""></div><div class="">I should really update withMemoryRebound's precondition to read:</div><div class=""><br class=""></div><div class="">&nbsp; If `count == 1` then `T` must be layout compatible with</div><div class="">&nbsp; `Pointee`. If `count &gt; 1`, then `T` must be mutually layout</div><div class="">&nbsp; compatible with `Pointee`.</div><div class=""><br class=""></div><div class="">You may be wondering why it's necessary to bind and rebind memory if the structures are "compatible". In general, you could have Swift code inside the closure that accesses `sockaddr` and swift code outside that accesses `sockaddr_in6`. We don't have a formal rule that says those two types are "related", so that could be miscompiled. "Related" is a type system concept that has to do with child/subclass relationships, "compatible" is an ABI concept that has to do with in-memory representation of types.</div><div class=""><br class=""></div><div class="">That's the theory. But in practice, the optimizer is going to have to treat sockaddr and sockaddr_in6 as related types simply because they are both imported from C and are allowed to alias in C land. In fact, if they were defined in Swift they wouldn't even be compatible because their overlapping members are not mutually compatible.</div><div class=""><br class=""></div><div class="">Even if one of the types were not imported, an opaque pointer cast would still work in this particular case because Swift code is never actually dereferencing the sockaddr pointer. It's just being passed off to an external C API.</div><div class=""><br class=""></div><div class="">So, the only real reason not to use an opaque pointer cast in this case is that someone reading your code likely won't understand what makes it valid and why they can't do the same thing in their code.</div></div></div></blockquote><div class=""><br class=""></div><div class=""><div class="">Excellent, thanks for the explanation.</div><div class=""><br class=""></div><div class="">I just realised I was somehow misreading ‘rebound’ to imply something trampoline-like which made worry about copying / indirection :)</div></div></div></div></blockquote><br class=""></div><div>&lt;groan&gt; The whole point of that method was to avoid punning!</div><div><br class=""></div><div>-Andy</div><br class=""></body></html>