[swift-evolution] [Draft] UnsafeRawPointer API
L. Mihalkovic
laurent.mihalkovic at gmail.com
Mon Jun 27 15:52:57 CDT 2016
Regards
(From mobile)
> On Jun 27, 2016, at 8:39 AM, Dave Abrahams <dabrahams at apple.com> wrote:
>
>
> on Fri Jun 24 2016, Andrew Trick <atrick-AT-apple.com> wrote:
>
>>> 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)
>
> The problem with this one is that T can be deduced based on type
> context. I think we ought to move away from that for operations like
> this one.
>
>> Option (2) UnsafePointer<T>(_: UnsafeRawPointer, to: T.self)
>
> I think you mean T.Type, not T.self, because this looks like a declaration.
>
> To evaluate, you have to look at the use-site:
>
> let p = UnsafePointer(r, to: Int.self)
>
> I don't find “to” to be descriptive enough. Maybe
toType
>
> let p = UnsafePointer(r, pointee: Int.self)
I find pointee a total aberation :)
>
> is better. But I hate that the language doesn't give us a way to say
> “don't deduce generic parameters here.” This is the only syntax that
> feels right, IMO:
>
> let p = UnsafePointer<Int>(r)
>
>> Option (3) UnsafeRawPointer.unsafeCast<T>(to: T.Type) ->
>> UnsafePointer<T>
>
> r.unsafeCast(to: Int.self)
>
> I don't see adding “unsafe” to the name of the operation as adding
> anything. It isn't any more unsafe than other UnsafeRawPointer
> operations.
It is unsafe in the sense that there are no guarantees that it is a sensible thing to do. I guess that means it is more 'noguaranteeexplicitorimpliedapplied' in the sense that it will like mechanically work, even if it produce an aberation as a result
> Also, it reads like we're casting the raw pointer to an
> Int, rather than to an UnsafePointer<Int>.
Really good one... But then instead of 'to' or 'pointee', something along the lines of 'wrappedType', which lookes a little less balerina-ish than pointee.....
> Also, how do you get an
> UnsafeMutablePointer?
>
>> Option (4) unsafeCast(rawPointer: UnsafeRawPointer, to: T.self) ->
>> UnsafePointer<T>
>
> This one won't read correctly for the same reasons as #3.
>
> r.cast(to: UnsafePointer<Int>.self)
>
> works better for me than any of the alternatives given our inability to
> get the One True Syntax.
>
>> ---
>> 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).
>
> Huh? I'm confused here. What you wrote looks like it's intended to be
> a regular method, in which case of course invoking it would require a raw
> pointer and wouldn't force you to write UnsafeRawPointer out anywhere.
>
> The only way it could force you to write UnsafeRawPointer would be if it
> was a static method, but in that case it has too few arguments.
>
>> 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`).
>
> r ?? someExpressionUsing(r!)
>
> best I can do.
>
>> 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?
>
> Yes!
>
>> 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
>
> Use sites! (yay)...
>
>> 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))
>
>
> foo(rawPtr.cast(to: UnsafePointer<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))
>
> foo(UnsafeRawPointer(ptrB).cast(to: UnsafePointer<A>.self))
>
> I don't believe in making these “double-hops” concise.
>
>> ---
>> 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))
>
> nullableFoo(UnsafeRawPointer(ptrB)?.cast(to: UnsafePointer<A>.self))
>
> You do the above with a failable init on UnsafeRawPointer that takes an
> optional UnsafePointer.
>
>> ---
>> 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)
>
> return UnsafeRawPointer(foo()).cast(to: UnsafePointer<B>.self)
>
> IMO-ly y'rs,
>
> --
> -Dave
More information about the swift-evolution
mailing list