[swift-evolution] [Draft] UnsafeRawPointer API
Andrew Trick
atrick at apple.com
Fri Jun 24 21:56:59 CDT 2016
> On Jun 24, 2016, at 11:22 AM, Andrew Trick via swift-evolution <swift-evolution at swift.org> wrote:
>
>> On Jun 24, 2016, at 11:17 AM, L. Mihalkovic <laurent.mihalkovic at gmail.com <mailto:laurent.mihalkovic at gmail.com>> wrote:
>>
>> I like the watch-what-you-wish-for warning of unsafeCast.
>
> I’ll try porting stdlib to the “UnsafeRawPointer.unsafeCast(to: T.Type)” syntax and see how bad it is.
I don't think there's a clear winner here. Let me enumerate some
options.
Option (1) UnsafePointer<T>(cast: UnsafeRawPointer)
Option (2) UnsafePointer<T>(_: UnsafeRawPointer, to: T.self)
Option (3) UnsafeRawPointer.unsafeCast<T>(to: T.Type) -> UnsafePointer<T>
Option (4) unsafeCast(rawPointer: UnsafeRawPointer, to: T.self) -> UnsafePointer<T>
---
Option (3) is the most explicit and searchable, and forces
UnsafeRawPointer to be spelled out in the conversion (unless you
already have a raw pointer). I like this because conceptually, you
need to cast to a raw pointer before casting to a new pointee
type, and casting a raw pointer to a typed pointer carries important
semantics beyond simply converting to a typed pointer. The main problem
with Option (3) is that optional raw pointers can't be converted
naturally (without using `map`).
Another thing I'm a little nervous about is confusing a cast of the
pointer value with a cast of the pointee type:
`unsafeBitCast(rawPtr, to: Int.self)`
is very different from
`rawPtr.unsafeCast(to: Int.self)`
Does this need to be clarified? If so, we can go back to the
`toPointee` label that I proposed earlier.
With that in mind, Option(4) is starting to look pretty good.
Examples:
---
Case 1: casting a raw pointer as an argument
func foo(_: UnsafePointer<A>)
let rawPtr = UnsafeRawPointer(...)
(1) foo(UnsafePointer(cast: rawPtr))
(2) foo(UnsafePointer(rawPtr, to: A.self))
(3) foo(rawPtr.unsafeCast(to: A.self))
(4) foo(unsafeCast(rawPointer: rawPtr, to: A.self))
---
Case 2: "recasting" a typed pointer argument
Note that typed pointer arguments are implicitly cast to raw pointer
arguments, so the conversion from PtrB to raw is implicit.
func foo(_: UnsafePointer<A>)
let ptrB = UnsafePointer<B>(...)
(1) foo(UnsafePointer(cast: ptrB))
(2) foo(UnsafePointer(ptrB, to: A.self))
(3) foo(UnsafeRawPointer(ptrB).unsafeCast(to: A.self))
(4) foo(unsafeCast(rawPointer: ptrB, to: A.self))
---
Case 3: Optional argument (only Option 3 is affected)
func nullableFoo(_: UnsafePointer<Int>?)
let ptrB: UnsafePointer<UInt>? = ...
(1) nullableFoo(UnsafePointer(cast: ptrB))
(2) nullableFoo(UnsafePointer(ptrB, to: A.self))
(3) nullableFoo(UnsafeRawPointer(ptrB).map { $0.unsafeCast(to: A.self) })
(4) nullableFoo(unsafeCast(rawPointer: ptrB, to: A.self))
---
Case 4: Return values
func foo() -> UnsafePointer<A>
func caller() -> UnsafePointer<B> { ...
(1) return UnsafePointer(cast: foo())
(2) return UnsafePointer(foo(), to: B.self)
(3) let rawPtr = UnsafeRawPointer(foo())
return rawPtr.unsafeCast(to: B.self)
(4) return unsafeCast(rawPointer: foo(), to: B.self)
-Andy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160624/fbd47f36/attachment.html>
More information about the swift-evolution
mailing list