> On Aug 20, 2016, at 4:02 AM, Michael Ferenduros via swift-users > <swift-users@swift.org> wrote: > >> >> On 20 Aug 2016, at 07:25, Andrew Trick <atr...@apple.com >> <mailto:atr...@apple.com>> wrote: >> >>> >>> On Aug 19, 2016, at 4:49 PM, Michael Ferenduros via swift-users >>> <swift-users@swift.org <mailto:swift-users@swift.org>> 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 :)
<groan> The whole point of that method was to avoid punning! -Andy
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users