> 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

Reply via email to