> On 20 Aug 2016, at 07:25, Andrew Trick <[email protected]> wrote: > >> >> On Aug 19, 2016, at 4:49 PM, Michael Ferenduros via swift-users >> <[email protected] <mailto:[email protected]>> wrote: >> >> >>>> On Aug 18, 2016, at 12:28 AM, Quinn The Eskimo! via swift-users >>>> <swift-users at swift.org <http://swift.org/>> wrote: >>>> >>>> >>>> On 17 Aug 2016, at 18:55, Martin R via swift-users <swift-users at >>>> swift.org <http://swift.org/>> wrote: >>>> >>>>> - Are both solutions correct, should one be preferred, or are both wrong? >>>> >>>> Your `withMemoryRebound` solution is correct. >>> 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 >>> https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md >>> >>> <https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md> >>> >>> <https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md >>> >>> <https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md>> >>> But this migration guide is more approachable… it’s still WIP: >>> https://gist.github.com/atrick/0283ae0e284610fd21ad6ed3f454a585 >>> <https://gist.github.com/atrick/0283ae0e284610fd21ad6ed3f454a585> >> >> I’m running into the same issues, which is making me wonder >> withMemoryRebound - socket functions expect an UnsafePointer<sockaddr>, 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<sockaddr> 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? > > Good point. I replied too hastily, but you’re about to find out why I didn’t > go into details… > > As you can see > <https://github.com/apple/swift/blob/master/stdlib/public/core/UnsafePointer.swift.gyb#L371>, > withMemoryRebound(to: T.self, capacity: count) actually does this: > - (re)binds memory to `count` `T` values > - executes the closure > - (re)binds memory to `count` `Pointee` values > > For `count == 1` and `MemoryLayout<T>.size < MemoryLayout<Pointee>.size` this > is valid and safe for "compatible" structs. The precondition on > `withMemoryRebound` states that `T` must be layout compatible with `Pointee`. > > aggregates (tuples, array storage, and structs), are layout > compatible with larger aggregates of the same kind if their common > elements are mutually layout compatible. > > I should really update withMemoryRebound's precondition to read: > > If `count == 1` then `T` must be layout compatible with > `Pointee`. If `count > 1`, then `T` must be mutually layout > compatible with `Pointee`. > > 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. > > 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. > > 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. > > 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.
Excellent, thanks for the explanation. I just realised I was somehow misreading ‘rebound’ to imply something trampoline-like which made worry about copying / indirection :)
_______________________________________________ swift-users mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-users
