gormster
(Morgan Harris)
1
I know that, in the grand scope of things, this is a non-problem. But I still find it curious, and a little odd.
func a(_ p: UnsafePointer<UInt32>) {
print(p)
}
func b(_ p: UnsafeBufferPointer<UInt32>) {
print(p)
}
let testArray: [UInt32] = [1, 2, 3, 4]
a(testArray)
// 0x0000600000abcdef
b(testArray)
// error: cannot convert value of type '[UInt32]' to expected argument type 'UnsafeBufferPointer<UInt32>'
The only difference between UnsafePointer and UnsafeBufferPointer is that the buffer pointer carries an element count, right? So why is Array allowed to implicitly cast to UnsafePointer but not UnsafeBufferPointer?
Yes, of course, one can (and should) use withUnsafeBufferPointer. I know. I also know that Array is not guaranteed to have contiguous storage, and withUnsafeBufferPointer might cause a copy (though I'm not sure if this ever actually happens in the standard library or Foundation). But it still seems weird to me. Why convert one kind of unsafe pointer implicitly, while the other (arguably safer) kind requires a pretty wordy function invocation?
I suspect the answer might be "C interop weirdness", but if there's more to it I'd be interested to know.
1 Like
jrose
(Jordan Rose)
2
That's pretty much it. All of the argument pointer conversions were intended for C interop, even though we didn't actually limit them to C functions, so they only support C types.
4 Likes
scanon
(Steve Canon)
3
It's worth considering whether or not we might be able to restrict some of these C interop conversions to only apply to functions imported from C, to avoid confusion (and subtle sources of unsafety).
5 Likes
gormster
(Morgan Harris)
4
I think that's honestly not a bad idea, with the small caveat that you will probably break a lot of existing code 
4 Likes
jrose
(Jordan Rose)
5
I’ve always pushed back on that because it means functions can’t be migrated from C to Swift. Though I guess we could say @exposeToC or whatever re-enables the conversions, when it comes to that.
scanon
(Steve Canon)
6
To migrate to Swift, you would "simply" add an explicit overload for the cases where the conversion actually makes sense (but ideally you would provide a better API in Swift anyway--simply migrating existing unsafe pointer functions to Swift means that you're replacing the implementation without benefiting from safer interfaces).
An explicit marker could also be an option, of course.
1 Like
jrose
(Jordan Rose)
7
Yeah, I was thinking specifically about the cases where you need to preserve the C ABI (or even just API), but it’s true you can always add overloads.
1 Like
scanon
(Steve Canon)
8
I think it would be pretty reasonable to tie this up with a formalized cdecl as "this function has C language semantics (including both mangling/visibility for C and pointer conversions).”
5 Likes