> 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

Reply via email to